Tree chain split memories notes
Excerpt definition:
- Heavy sons: the number of all sons of neutrons tree nodes father node up (size maximum) nodes;
- Light son: father node in addition to heavy son's son;
- Multiple edges: father, son nodes and re-connected into the edge;
- Light Edge: Father son nodes and light even into the edge;
- Heavy chain: the path formed by connecting a plurality of multiple edges;
- Light chain: a path formed by connecting a plurality of light sides;
Then there is no then the
All the stuff about "light" words are futile
A bit better understanding of the drawing,
The red dots mark the starting point of a heavy chain
We found that the heavy side edges are No. 1,2,3,4,8,10,11
More importantly, all nodes in a heavy chain (also considered a node)
dfs sequence in the tree defining the chain split is also a little different
Because in order to facilitate maintenance, we DFS order nodes on a continuous chain
Chain famous tree split in two dfs dfs pretreatment sequence, depth and severity of his son, light and heavy chains, the size of the subtrees
The main idea of the tree and then split the chain is on the heavy maintenance of a variety of advanced data structures, for example segment tree, balanced tree ......
Okay, so
Board problem Code:
#include <bits / STDC ++ H.> the using namespace STD; const int N = 200005 ; long long n-, m, R & lt, P; // number of nodes of the tree, the number of operations, and the root number modulo the number of long Long Val [N]; // initial weights of each node Long Long CNT = 0 , HED [N], TAL [N * 2 ], NXT [N * 2 ]; Long Long F [N]; // father node Long Long D [N]; // node depth Long Long size [N]; // subtree node number Long Long S [N] = {0 }; // weight son ID Long Long ID [N]; // the DFS sequence Long Long Rk [N]; // number of the corresponding sequence in the original dfs tree Long Long T [N]; // chain top Long Long = TOT 0 ; // timestamp struct ST { Long Long value; Long Long LZT; } T [N << 2 ]; // segment tree void addege ( Long Long A, Long Long B) { CNT++; tal[cnt]=b; nxt[cnt]=hed[a]; hed[a]=cnt; } void dfs1(long long u,long long fa,long long dis){//第一遍dfs d[u]=dis;//节点初始化 f[u]=fa; size[u]=1; for(long long i=hed[u];i;i=nxt[i]){ long long v=tal[i]; if(v==fa) Continue ; DFS1 (V, U, DIS + . 1 ); // iterate son size [U] + = size [V]; // update the number of sub-tree nodes IF (S [U] == 0 ) S [U] = V; the else IF (size [S [U]] <size [V]) S [U] = V; // select weight son } } void DFS2 ( Long Long U, Long Long GF) { // current node, chain top T [U] = GF; ID [U] = ++ TOT; Rk [TOT] = U; IF (! S [U]) return ; dfs2(s[u],gf); for(long long i=hed[u];i;i=nxt[i]){ long long v=tal[i]; if(v==f[u]) continue; if(v==s[u]) continue; dfs2(v,v); } } long long len(long long l,long long r){return r-l+1;} void push_up(long long num){ t[num].value=(t[num<<1].value+t[num<<1|1].value)%p; } void push_down(long long l,long long r,long long num){ if(t[num].LZT){ long long mid=(l+r)>>1; t[num<<1].LZT+=t[num].LZT; t[num<<1|1].LZT+=t[num].LZT; t[num<<1].value+=len(l,mid)*t[num].LZT; t[num<<1].value%=p; t[num<<1|1].value+=len(mid+1,r)*t[num].LZT; t[num<<1|1].value%=p; t[num].LZT=0; } } void build(long long l,long long r,long long num){ if(l==r){ t[num].LZT=0; t[num].value=val[Rk[l]]%p; return; } long long mid=(l+r)>>1; build(l,mid,num<<1),build(mid+1,r,num<<1|1); push_up(num); } void upt(long long l,long long r,long long num,long long L,long long R,long long X){ if(l>=L&&r<=R){ t[num].LZT+=X; t[num].LZT%=p; t[num].value+=len(l,r)*X; t[num].value%=p; return; } if(l>R||r<L) return; long long mid=(l+r)>>1; push_down(l,r,num); upt(l,mid,num<<1,L,R,X); upt(mid+1,r,num<<1|1,L,R,X); push_up(num); } long long qus(long long l,long long r,long long num,long long L,long long R){ if(l>=L&&r<=R){ return t[num].value%p; } if(l>R||r<L) return 0; long long mid=(l+r)>>1; push_down(l,r,num); return (qus(l,mid,num<<1,L,R)+qus(mid+1,r,num<<1|1,L,R))%p; } long long ask(long long x,long long y){ long long sum=0; while(T[x]!=T[y]){ if(d[T[x]]<d[T[y]]) swap(x,y); sum+=qus(1,n,1,id[T[x]],id[x]); sum%=p; x=f[T[x]]; } if(d[x]>d[y]) swap(x,y); return (sum+qus(1,n,1,id[x],id[y]))%p; } void pus(long long x,long long y,long long z){ while(T[x]!=T[y]){ if(d[T[x]]<d[T[y]]) swap(x,y); upt(1,n,1,id[T[x]],id[x],z); x=f[T[x]]; } if(d[x]>d[y]) swap(x,y); upt(1,n,1,id[x],id[y],z); } int main(){ scanf("%lld%lld%lld%lld",&n,&m,&r,&p); for(long long i=1;i<=n;i++){ scanf(" % LLD " , & Val [I]); } for ( Long Long I = . 1 ; I <n-; I ++ ) { Long Long A, B; Scanf ( " % LLD% LLD " , & A, & B); addege (a, B); addege (B, a); } DFS1 (R & lt, - . 1 , . 1 ); // starting from the root, the depth of each node is determined, the number of sub-tree nodes, father, son number and weight / / ↑ // node, a parent node, the depth DFS2 (R & lt, R & lt); // second pass to obtain remaining information dfs @-------------------------------------------------- ------------------------ // Next, enter the segment tree section! Build ( . 1 , n-, . 1 ); // achievements of the while (M-- ) { Long Long opt; Scanf ( " % LLD " , & opt); IF (== opt . 1 ) { Long Long X, Y, Z; Scanf ( " %% LLD LLD LLD% " , & X, & Y, & Z); Z % = P; PUS (X, Y, Z); } the else if(opt==2){ long long x,y; scanf("%lld%lld",&x,&y); printf("%lld\n",ask(x,y)%p); } else if(opt==3){ long long x,y; scanf("%lld%lld",&x,&y); y%=p; upt(1,n,1,id[x],id[x]+size[x]-1,y); } else{ long long x; scanf("%lld",&x); printf("%lld\n",qus(1,n,1,id[x],id[x]+size[x]-1)%p); } } return 0; }