Cancer thing ... but a league actually gone out over the years about the three tree cross ... Oh ~
question type
As the name suggests what belongs to graph theory. Based on the data structures: segment tree
Operation 1: Format: 1 shows a tree XYZ values of all the nodes on the shortest path from the node x to y plus z are
Operation 2: Format: 2 XY indicates finding a tree node from x to y value on the shortest path, and all nodes
Operation 3: Format: 3 x will be represented by an xz all nodes within the subtree root values are plus z
Operation 4: Format: 4 x values represent all nodes within the subtree root node seeking and at x
Principle of the method
... I feel that I have to describe has nothing to say, as I think the best moved the blog to understand it.
Luo Valley Daily: Tree chain split
Pre-knowledge should be added to a LCA, but a tree difference seems less useful.
Said very clearly, but at least for me, konjac, and his board code that does make people very uncomfortable
So here we attach a link to its board title Code (excerpt from zengqinyi from luogu)
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #define Rint register int #define mem(a,b) memset(a,(b),sizeof(a)) #define Temp template<typename T> using namespace std; typedef long long LL; Temp inline void read(T &x){ x=0;T w=1,ch=getchar(); while(!isdigit(ch)&&ch!='-')ch=getchar(); if(ch=='-')w=-1,ch=getchar(); while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar(); x=x*w; } #define mid ((l+r)>>1) #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define len (r-l+1) const int maxn=200000+10; int n,m,r,mod; //见题意 intE, BEG [MAXN], NEX [MAXN], to [MAXN], W [MAXN], wt [MAXN]; // front chain to star array, w [], wt [] array start point right int A [ << MAXN 2 ], Laz [MAXN << 2 ]; // segment tree array, lazy operation int Son [MAXN], ID [MAXN], FA [MAXN], CNT, DEP [MAXN], SIZ [MAXN], top [MAXN]; // son [] weight son number, id [] a new number, fa [] parent node, cnt dfs_clock / dfs sequence, dep [] depth, siz [] subtree size, top [] current top strand node int RES = 0 ; // query answer inline void the add ( int X, int Y) { // before the star plus side chain to [E ++] = Y; NEX [E] = BEG [X]; BEG [ X] =e; } //-------------------------------------- 以下为线段树 inline void pushdown(int rt,int lenn){ laz[rt<<1]+=laz[rt]; laz[rt<<1|1]+=laz[rt]; a[rt<<1]+=laz[rt]*(lenn-(lenn>>1)); a[rt<<1|1]+=laz[rt]*(lenn>>1); a[rt<<1]%=mod; a[rt<<1|1]%=mod; laz[rt]=0; } inline void build(int rt,int l,int r){ if(l==r){ a[rt]=wt[l]; if(a[rt]>mod)a[rt]%=mod; return; } build(lson); build(rson); a[rt]=(a[rt<<1]+a[rt<<1|1])%mod; } inline void query(int rt,int l,int r,int L,int R){ if(L<=l&&r<=R){res+=a[rt];res%=mod;return;} else{ if(laz[rt])pushdown(rt,len); if(L<=mid)query(lson,L,R); if(R>mid)query(rson,L,R); } } inline void update(int rt,int l,int r,int L,int R,int k){ if(L<=l&&r<=R){ laz[rt]+=k; a[rt]+=k*len; } else{ if(laz[rt])pushdown(rt,len); if(L<=mid)update(lson,L,R,k); if(R>mid)update(rson,L,R,k); a[rt]=(a[rt<<1]+a[rt<<1|1])%mod; } } //---------------------------------以上为线段树 inline int qRange(int x,int y){ int ans=0; while(top[x]!=top[y]){// When two points not on the same strand IF (DEP [Top [x]] <DEP [Top [Y]]) the swap (x, Y); // the point x where the top of the chain to a depth deeper the point RES = 0 ; Query ( . 1 , . 1 , n-, ID [top [x]], ID [x]); // ANS plus x to the point x where the chain to the top section of this section and the right point ANS + = RES ; ANS % = MOD; // press that Italy modulo x = FA [top [x]]; // the x jump point above that of the top strand where a point x } // until the two points in the chain the IF (DEP [x]> DEP [Y]) the swap (x, Y); // the point x of the point deeper RES = 0 ; Query ( . 1 , . 1, n-, ID [X], ID [Y]); // time interval plus the two points at this time and to ANS + = RES; return ANS% MOD; } inline void updRange ( int X, int Y , int K) { // supra K% = MOD; the while ! (Top [X] = Top [Y]) { IF (DEP [Top [X]] < DEP [Top [Y]]) the swap (X, Y ); Update ( . 1 , . 1 , n-, ID [Top [X]], ID [X], K); X = FA [Top [X]]; } IF (DEP [X]> DEP [Y]) the swap (X, Y); Update ( . 1, . 1 , n-, ID [X], ID [Y], K); } inline int qSon ( int X) { RES = 0 ; Query ( . 1 , . 1 , n-, ID [X], ID [X] + SIZ [X] - . 1 ); // subtree is the right end section ID [X] + SIZ [X] -1 return RES; } inline void updSon ( int X, int K) { // supra Update ( . 1 , . 1 , n-, ID [X], ID [X] + SIZ [X] - . 1 , K); } inline void DFS1 ( int X,int F, int Deep) { // X current node, f father, deep depth of DEP [X] = Deep; // tag for each depth point FA [X] = F; // tag fathers each point SIZ [ X] = . 1 ; // tag for each non-leaf nodes of the subtree size int Maxson = - . 1 ; // record the number of son son weight for (I Rint = BEG [X]; I; I = NEX [I]) { int Y = to [I]; IF (Y == F) Continue ; // if the father Continue DFS1 (Y, X, Deep + . 1 ); // DFS his son siz [x] + = siz [ y] ; //The number applied to its body it son IF (SIZ [Y]> Maxson) Son [X] = Y, Maxson = SIZ [Y]; // tag weight of each non-leaf nodes son ID } } inline void DFS2 ( int X, int Topf) { // X current node, the currently topmost Topf chain node ID [X] = CNT ++; // tag for each point, the new numbering wt [CNT] = W [X]; / / the initial value of each point is assigned numbers up to the new top [X] = Topf; // the top of the point where the chain IF (son [X]!) return ; // if no son returns dfs2 (son [x ], Topf); // by weight of the first son process, then the processing sequence of the light son recursive process for (I Rint = BEG [X]; I; I = NEX [I]) { int Y =to [I]; IF (FA == Y [X] || Y == Son [X]) Continue ; DFS2 (Y, Y); // for each son has a light chain from the beginning of its own } } int main () { Read (n-); Read (m); Read (R & lt); Read (MOD); for (Rint I = . 1 ; I <= n-; I ++ ) Read (W [I]); for ( RINT I = . 1 ; I <n-; I ++ ) { int A, B; Read (A); Read (B); the Add (A, B); the Add (B, A); } DFS1 (R & lt, 0 , . 1 ) ; DFS2 (R & lt, R & lt); Build ( . 1 , . 1 , n-); while(m--){ int k,x,y,z; read(k); if(k==1){ read(x);read(y);read(z); updRange(x,y,z); } else if(k==2){ read(x);read(y); printf("%d\n",qRange(x,y)); } else if(k==3){ read(x);read(y); updSon(x,y); } else{ read(x); printf("%d\n",qSon(x)); } } }
Step analysis
Such a long thing, you say to backplane daughter I really do not believe.
I still understand what steps to remember.
1. recorded using dfs subtree size, the parent node array, and the array select depth weight son
2. Mark Dfs each point sequence, and mark the node sequence corresponding to Sequence Dfs. (A pair of mutually mapped). Recording start end of each heavy chain. When making dfs order, first traversal heavy son, in order to ensure continuous heavy chain sequence Dfs. Then go light chain
3. For
All tree nodes from x to y shortest path node values plus z
Tree request from x to y values of all nodes in the shortest path of nodes and
That is associated with the shortest path operations, we are not in a situation need to put on a chain disposed of, then when do the same chain of intervals and.
4. For
X is a root node will be the subtree nodes values are all plus z
Find all the nodes in the value x is a root node of the subtree and
This sub tree-related operations, because our numbers are continuous dfs directly modify the interval (incoming dfs order) range query.