HDU 6162 Ch’s gift
来源:互联网 发布:城市地图制作软件 编辑:程序博客网 时间:2024/06/05 06:09
HDU 6162 Ch’s gift
线段树,离线
题意
给一棵树,每次询问:uv两点间的路上(包括uv),点权在ab之间的所有点点权和。
思路
由于没有修改操作,一个显然的想法是离线处理所有问题
将询问拆成1-x,1-y,1-LCA(x,y),则处理的问题转化为从根到节点的链上的问题。
解决这个问题,我们可以在dfs时向treap插入当前的数,在退出时删除这个数,并且每次维护在该点上的答案。
两种思路,在线的树链剖分加主席树维护,离线的LCA加线段树/treap。我写的是离线LCA加线段树。线段树当成权值线段树用,所以离散化特别麻烦,可能treap更简单。
将每个询问拆开,u到v拆成:(1~u)+(1~v)-(2*1~LCA(u,v))+LCA(u,v)。如果LCA(u,v)权在询问上下界之间,就作为附加值加上,否则不加。
因为权值线段树要求范围是1到n,所以需要离散化,注意各种边界问题。
代码
#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<set>#include<iostream>#include<vector>#include<queue>#include<regex>#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define M(a,b) memset(a,b,sizeof(a))using namespace std;const int MAXN=100005;const int oo=0x3f3f3f3f;typedef long long LL;//树结构struct Edge{ int to, ne;}e[MAXN<<1];int head[MAXN], v[MAXN], edgenum;void addedge(int u, int v){ e[edgenum].to=v, e[edgenum].ne=head[u], head[u]=edgenum++; e[edgenum].to=u, e[edgenum].ne=head[v], head[v]=edgenum++;}//LCAint parent[20][MAXN];int depth[MAXN];void ddfs(int v, int p, int d){ parent[0][v]=p; depth[v]=d; for(int i=head[v];~i;i=e[i].ne) { if(e[i].to!=p) ddfs(e[i].to, v, d+1); }}void init(int V){ ddfs(1, -1, 0); for(int k=0;k+1<20;k++) { for(int v=1;v<=V;v++) { if(parent[k][v]<0) parent[k+1][v]=-1; else parent[k+1][v]=parent[k][parent[k][v]]; } }}int lca(int u, int v){ if(depth[u]>depth[v]) swap(u, v); for(int k=0;k<20;k++) { if((depth[v]-depth[u])>>k&1) v=parent[k][v]; } if(u==v) return u; for(int k=20-1;k>=0;k--) { if(parent[k][u]!=parent[k][v]) { u=parent[k][u]; v=parent[k][v]; } } return parent[0][u];}//点权与哈希struct Val{ LL val; int i; int ha;}val[MAXN];bool cmp1(Val a, Val b){ return a.val<b.val;}bool cmp2(Val a, Val b){ return a.i<b.i;}LL ha[MAXN];//分解询问struct Query{ int x, y; int i, k; LL res; int ne; int up, dw; LL add;}q[MAXN*3];int qnum, headq[MAXN];//链式前向星储存询问//线段树LL stree[MAXN<<2];void pushup(int rt) { stree[rt]=stree[rt<<1]+stree[rt<<1|1]; }void build() { M(stree, 0); }void update(int pos, LL c, int l, int r, int rt){ if(l==r) { stree[rt]+=c;return; } int mid=(l+r)>>1; if(pos<=mid) update(pos, c, lson); else update(pos, c, rson); pushup(rt);}LL query(int L, int R, int l, int r, int rt){ if(L<=l&&r<=R) return stree[rt]; int mid=(l+r)>>1; LL res=0; if(L<=mid) res+=query(L, R, lson); if(mid<R) res+=query(L, R, rson); return res;}//dfs的solvevoid dfs(int u, int fa, int n){ update(val[u].ha, val[u].val, 1, n, 1); for(int i=headq[u];~i;i=q[i].ne) { int l=q[i].dw, r=q[i].up; q[i].res=query(l, r, 1, n, 1); } for(int i=head[u];~i;i=e[i].ne) { int to=e[i].to; if(to!=fa) dfs(to, u, n); } update(val[u].ha, -val[u].val, 1, n, 1);}int main(){ //freopen("in.txt", "r", stdin); //freopen("ou.txt", "w", stdout); int n, m; while(scanf("%d%d", &n, &m)==2) { //初始化 edgenum=1, qnum=1;M(head, -1), M(headq, -1); build(); //点权与哈希 for(int i=1;i<=n;i++) { scanf("%lld", &val[i].val), val[i].i=i; } sort(val+1, val+n+1, cmp1); int tt=1;ha[tt]=val[1].val-1;tt++;//加前哨兵 val[1].ha=tt;ha[tt]=val[1].val; for(int i=2;i<=n;i++) { if(val[i].val>val[i-1].val) val[i].ha=++tt, ha[tt]=val[i].val; else val[i].ha=tt; } sort(val+1, val+n+1, cmp2); //树结构 for(int i=1;i<n;i++) { int u, v;scanf("%d%d", &u, &v); addedge(u, v); } init(n);//LCA初始化 //分解询问 for(int i=1;i<=m;i++) { int x, y, up, dw;scanf("%d%d%d%d", &x, &y, &dw, &up); int u=lca(x, y); q[qnum].x=1, q[qnum].y=x, q[qnum].i=i, q[qnum].k=1; q[qnum].dw=lower_bound(ha+1, ha+1+tt, dw)-ha, q[qnum].up=lower_bound(ha+1, ha+1+tt, up)-ha; if(up<ha[q[qnum].up]) q[qnum].up--;//注意特判上端点 q[qnum].ne=headq[x], headq[x]=qnum++; q[qnum].x=1, q[qnum].y=y, q[qnum].i=i, q[qnum].k=1; q[qnum].dw=lower_bound(ha+1, ha+1+tt, dw)-ha, q[qnum].up=lower_bound(ha+1, ha+1+tt, up)-ha; if(up<ha[q[qnum].up]) q[qnum].up--;//注意特判上端点 q[qnum].ne=headq[y], headq[y]=qnum++; q[qnum].x=1, q[qnum].y=u, q[qnum].i=i, q[qnum].k=-1; q[qnum].dw=lower_bound(ha+1, ha+1+tt, dw)-ha, q[qnum].up=lower_bound(ha+1, ha+1+tt, up)-ha; if(up<ha[q[qnum].up]) q[qnum].up--;//注意特判上端点 q[qnum].ne=headq[u], headq[u]=qnum++; q[qnum-1].add=((val[u].val>=dw&&val[u].val<=up) ? val[u].val : 0);//是否附加LCA的权 } dfs(1, -1, tt); for(int i=1;i<=3*m;i+=3) { LL ans=q[i].res+q[i+1].res-2*q[i+2].res+q[i+2].add; printf("%lld%c", ans, i==3*m-2 ? '\n' : ' '); } } //system("pause"); return 0;}
阅读全文
0 0
- hdu 6162 Ch’s gift
- HDU 6162 Ch’s gift
- HDU 6162 Ch’s gift
- HDU 6162 Ch's gift
- HDU 6162 Ch’s gift
- Ch’s gift HDU
- Ch’s gift HDU
- Ch’s gift HDU
- hdu-6162 Ch’s gift 主席树
- hdu-6162 Ch’s gift(树链剖分)
- HDU 6162 Ch’s gift(LCA)
- hdu 6162 Ch’s gift【树链剖分】
- hdu 6162 Ch’s gift(树链刨分)
- hdu 6162 Ch’s gift(主席树+树链剖分)
- HDU 6162 Ch’s gift (2017多校9
- HDU 6162 Ch’s gift(树链剖分+线段树)
- hdu 6162 Ch’s gift(主席树)
- Hdu 6162 Ch’s gift(Tarjan+dp)
- 相似度算法
- HDU 6168 Numbers(数列,思维)
- 《剑指offer》问题5 替换空格 Java实现
- Hadoop发行版本比较与选型
- Fizz Buzz
- HDU 6162 Ch’s gift
- 数据结构 图(C++实现代码)
- ThreadPoolTaskExecutor的配置解释
- 【Redis手册二】redis.conf 配置参数说明
- Java-最大堆的排序,插入,删除
- 分金子(360公司2017春招真题)
- Rhel7链路聚合
- [算法]行列递增数组中查找某个元素
- rabbitMQ与Spring集成