hdu3966 树链剖分(入门,点)
2016-10-03 14:39
148 查看
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <vector> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll; const int N=50005; int siz ,top ,son ,dep ,tid ,rk ,fa ; //siz[]数组,用来保存以x为根的子树节点个数 //top[]数组,用来保存当前节点的所在链的顶端节点 //son[]数组,用来保存重儿子 //dep[]数组,用来保存当前节点的深度 //fa[]数组,用来保存当前节点的父亲 //tid[]数组,用来保存树中每个节点剖分后的新编号 //rk[]数组,线段树中编号对应的原节点编号 int cnt,tim,n,m,p,a ; struct node { int next,to; } edge[N*2]; int head ; void intt() { cnt=tim=0; memset(son,-1,sizeof(son)); memset(head,-1,sizeof(head)); } void add(int u,int v) { edge[++cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; } void dfs1(int u,int pre/*fa*/,int de) {/*求出每个点的深度和父节点,和重儿子*/ dep[u]=de;fa[u]=pre;siz[u]=1; for(int i=head[u]; ~i; i=edge[i].next) { int v=edge[i].to; if(v!=pre) { dfs1(v,u,de+1); siz[u]+=siz[v]; if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v; } } } void dfs2(int u,int tp) {/*给链编号,形成一一对应的关系*/ top[u]=tp; tid[u]=++tim; rk[tid[u]]=u; if(son[u]==-1) return; dfs2(son[u],tp); for(int i=head[u]; ~i; i=edge[i].next) { int v=edge[i].to; if(v!=son[u]/*不是u的重儿子*/&&v!=fa[u]/*不是u的父节点*/) dfs2(v,v); } } #define ls l,mid,rt<<1 #define rs mid+1,r,rt<<1|1 int sum[4*N],lazy[4*N]; void up(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void down(int rt,int len) { if(lazy[rt]) { lazy[rt<<1]+=lazy[rt]; lazy[rt<<1|1]+=lazy[rt]; sum[rt<<1]+=lazy[rt]*(len-(len>>1)); sum[rt<<1|1]+=lazy[rt]*(len>>1); lazy[rt]=0; } } void build(int l,int r,int rt) { lazy[rt]=0; if(l==r) { sum[rt]=a[rk[l]];//初始值为原编号的数量 return; } int mid=(l+r)>>1; build(ls); build(rs); up(rt); } void update(int L,int R,int val,int l,int r,int rt) { if(L<=l&&r<=R) { lazy[rt]+=val; sum[rt]+=val*(r-l+1); return; } down(rt,r-l+1); int mid=(l+r)>>1; if(mid>=L) update(L,R,val,ls); if(mid<R) update(L,R,val,rs); up(rt); } int query(int pos,int l,int r,int rt) { if(l==r) return sum[rt]; down(rt,r-l+1); int mid=(l+r)>>1; int ret=0; if(pos<=mid) ret+=query(pos,ls); else ret+=query(pos,rs); return ret; } /* 如果不在一条链上,那么比较x,y点链顶的父节点深度,更新深度深的链(进行交换,把深度深的赋予为x),更新完后,将范围调整到y--fa[top[x]],然后一直迭代,直到在同一个链上。 */ void Change(int x,int y,int val) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); update(tid[top[x]],tid[x],val,1,n,1); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); update(tid[x],tid[y],val,1,n,1); } int main() { while(~scanf("%d%d%d",&n,&m,&p)) { intt(); for(int i=1; i<=n; i++) scanf("%d",&a[i]); while(m--) { int u,v; scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs1(1,0,0); dfs2(1,1); build(1,n,1); while(p--) { char oper[2]; int aa,b,c; scanf("%s",oper); if(oper[0]=='Q') { scanf("%d",&aa); printf("%d\n",query(tid[aa],1,n,1)); } else { scanf("%d%d%d",&aa,&b,&c); if(oper[0]=='D') c=-c; Change(aa,b,c); } } } }
相关文章推荐
- HDU3966(树链剖分(点权)入门)链分治
- 树链剖分入门-Hdu3966 Aragorn's Story
- 树链剖分学习 (hdu3966)
- hdu3966 Aragorn's Story(树链剖分)
- 树链剖分 入门
- 树链剖分(线段树区间更新求和(lazy操作)hdu3966)
- HDU3966 Aragorn's Story(树链剖分 点权 模版题)
- LightOJ 1348 Aladdin and the Return Journey【树链剖分入门题】
- HDU3966-Aragorn's Story-树链剖分-点权
- 树链剖分 hdu3966 (kuangbin)
- SPOJ 375. Query on a tree (树链剖分入门)
- HDU3966(树链剖分+线段树区间更新,单点查询)
- hdu3966 Aragorn's Story 树链剖分
- Gym 101138J Valentina and the Gift Tree 以及树链剖分入门讲解
- 树链剖分(线段树区间更新求和(lazy操作)hdu3966)
- hdu3966(树链剖分)
- 【HDU3966】Aragorn's Story-树链剖分或LCT维护路径
- hdu3966 树链剖分+成段更新
- hdu3966(树链剖分)
- 树链剖分入门 poj 2763