AC Channel: http://acm.hdu.edu.cn/showproblem.php?pid=3966
[to the effect of the topic]
Each point in a tree has a value that supports three actions at a time: the weights of all nodes on the [a, b] path plus k, minus K for all nodes on the [a, b] path, and the weights of a are queried.
Analysis
This is a tree-chain split template problem.
The tree chain is a chain of trees, which are stored in a data structure and maintained by the data structure.
Suppose the tree is a chain, this problem is of course very good to do: The chain is directly stored with a line segment, because [A, a] path in the segment tree is also a continuous paragraph, then modify a section is log (n), the query node can also log (n) to complete.
But given a tree, the path between the two points of the tree is the only certainty, but it is not necessarily a continuous paragraph in the line tree.
As a rule, you need an algorithm that divides the paths of each tree into successive segments.
This is the tree chain split up.
First define the concept of the heavy son: V is the heavy son of U, when and only if size (v) >=size (V ') is set for the Son v ' of any U. It is the son of the son of U who is the largest of the sons.
Tree chains divide the tree into heavy chains and light edges, and heavy chains refer to the chains in which each node is attached to its heavy son, and the Son is attached to its heavy grandson. A light edge is an edge that joins a heavy chain.
[I don't have a picture here.] Yaotu Find someone else: http://blog.sina.com.cn/s/blog_7a1746820100wp67.html This picture is actually not very good-looking]
Through such a division, there is a graceful nature: any two-point path between the maximum log (n) heavy chain.
Then the points on the heavy chain can be stored continuously in the segment tree, each time the path is divided into a number of heavy chain parts to be processed.
In this way, each path processing is log (n) *log (n).
Specific steps:
First over DFS. Deal with something: the size of each node's tree, the weight of each point, the depth of each point [this is useful when dividing the path], the parent node for each of the nodes.
And then again DFS. For each point designator, note the serial number of the heavy chain, while recording the top node of the heavy chain where each point is located [how to do this can be seen in detail code]
Then build a line tree: the same way as usual.
Inquiry: Ask in the line tree, remember to send the next mark is good.
Modify: Think how to divide, if asked two points, assume that is X, Y.
When x, Y is in the same heavy chain: directly with the segment tree's interval modification, when not the same heavy chain, you need to move them to the same heavy chain.
First of all, X, Y is the heavy chain, whose upper distance is farther from the root, assuming x, then the X to the top of its heavy chain of the Father node [so moved to another heavy chain], but also the X to the top of the heavy chain in the segment tree to add tag.
In turn, you can wait until x, Y is on the same heavy chain. [specific also can see code]
Hope that through this problem, we can probably understand the idea of tree chain split ...
Offer code:
#include <cstdio>#include<cstring>#include<algorithm>using namespaceStd;inlineint inch(){ intx=0, f=1;CharCh=GetChar (); while((ch>'9'|| ch<'0') && ch!='-') ch=GetChar (); if(ch=='-') f=-1, ch=GetChar (); while(ch>='0'&& ch<='9') x=x*Ten+ch-'0', ch=GetChar (); returnx*F;}Const intmaxn=50010;intn,m,q;intCNT;intA[MAXN],ID[MAXN],IDEX,RK[MAXN];intDEPTH[MAXN],SZ[MAXN],FA[MAXN];intTOP[MAXN],SON[MAXN],HEAD[MAXN];Charord[2];structspot{intData,next;} SPOT[MAXN<<1];#defineNow Spot[pt].data#defineThen Spot[pt].nextstructnode{intDT,TG;} S[MAXN<<2];inlinevoidAddintUintv) {Spot[cnt].data=v;spot[cnt].next=head[u];head[u]=cnt++; Spot[cnt].data=u;spot[cnt].next=head[v];head[v]=cnt++;}voidDFS1 (intXintf) {Sz[x]=1, fa[x]=F; for(intPT=HEAD[X];p t!=-1=p2=Then )if(now!=f) {Depth[now]=depth[x]+1; DFS1 (NOW,X); SZ[X]+=Sz[now]; if(son[x]<0|| Sz[now]>Sz[son[x]]) son[x]=Now ; }}voidDFS2 (intXintTP) {Top[x]=tp,id[x]=++idex,rk[id[x]]=x; if(son[x]<0)return; DFS2 (SON[X],TP); for(intPT=HEAD[X];p t!=-1=p2=Then )if(Now!=fa[x] && now!=son[x]) DFS2 (Now,now);}voidBuildintLintRintRT) {S[rt].dt=s[rt].tg=0; if(l==R) {S[rt].dt=a[rk[l]];return; } intMid= (l+r) >>1; Build (L,mid,rt<<1); Build (Mid+1,r,rt<<1|1);} InlinevoidPush_down (intx) { if(S[X].TG) {s[x<<1].tg+=s[x].tg,s[x<<1].dt+=S[X].TG; S[x<<1|1].tg+=s[x].tg,s[x<<1|1].dt+=S[X].TG; S[X].TG=0; }}voidAdd_tag (intLintRintXintYintRtintval) { if(L==x && r==y) {S[rt].dt+=val,s[rt].tg+=Val; return; } intMid= (l+r) >>1; if(Y<=mid) Add_tag (l,mid,x,y,rt<<1, Val); Else if(X>mid) Add_tag (mid+1,r,x,y,rt<<1|1, Val); ElseAdd_tag (l,mid,x,mid,rt<<1, Val), Add_tag (mid+1, r,mid+1,y,rt<<1|1, Val);}intQueryintLintRintRtintk) { if(l==R)returnS[rt].dt; Push_down (RT); intMid= (l+r) >>1; if(K<=mid)returnQuery (l,mid,rt<<1, K); Else returnQuery (mid+1,r,rt<<1|1, k);}voidModifyintXintYintval) { while(top[x]!=Top[y]) { if(depth[top[x]]<Depth[top[y]]) swap (x, y); Add_tag (1, N,id[top[x]],id[x],1, Val); X=Fa[top[x]]; } if(id[x]>Id[y]) swap (x, y); Add_tag (1, N,id[x],id[y],1, Val);}intMain () {#ifndef Online_judge freopen ("3966.in","R", stdin); Freopen ("3966.out","W", stdout);#endif intu,v,x; while(~SCANF ("%d%d%d",&n,&m,&q)) {Idex=cnt=0; for(intI=1; i<=n;i++) A[i]=inch(), head[i]=son[i]=-1; for(intI=1; i<n;i++) U=inch(), v=inch(), add (U,V); DFS1 (1,0); DFS2 (1,1); Build (1N1); while(q--) {scanf ("%s", Ord); if(ord[0]=='Q') {x=inch(); printf ("%d\n", Query (1N1, id[x])); } Else{u=inch(), v=inch(), x=inch(); if(ord[0]=='D') x=-x; Modify (U,V,X); } } } return 0;}
View Code
Getting Started with tree chain-hdu3966 Aragorn ' s story