Detailed: https: //www.cnblogs.com/ivanovcraft/p/9019090.html
Essence tree is split chain sequence
In order to try to take the heavy chain, make possible a tree node decomposed into fewer chains collectively, as a continuous strand and the data structure is easily maintainable
The process has split twice dfs:
dfs1: find recrystallized point, establishing the depth of each point, the process may determine: sz [i], dep [i], fa [i], son [i]
void dfs1( int u ,int f ){ sz[u] = 1; for( int i = head[u]; i ;i = edge[i].next ){ int v = edge[i].to; if( v == f )continue; dep[v] = dep[u] + 1; fa[v] = u; dfs1( v ,u ); sz[u] += sz[v]; if( sz[v] >sz[ son[u] ] )son[u] = v; } }
dfs2: heavy chain linked into the node (to identify top [i]), and the order of the link as a chain sequence present in the array (dfn [i]), the process may determine: dfn, top, rnk
void dfs2( int u ,int t ){ dfn[u] = ++tot; top[u] = t; rnk[tot] = u; if( son[u] )dfs2( son[u] ,t ); for( int i = head[u] ;i ;i = edge[i].next ){ int v = edge[i].to; if( v!= fa[u] && v!= son[u] )dfs2(v,v); } }
Split after the segment tree data structure may be utilized, and other Fenwick tree decomposition of the chain after maintenance, given two nodes x, y, update and query operations therebetween, this process is:
1. If x, y in a heavy chain (top [x] == top [y]), the data structure can be used directly x to y a contiguous chain that operate directly
2. If the x, y not on one heavy chain (top [x]! = Top [y]), find the deeper nodes (dep [fx]> dep [fy]) x, fx that the first x short operating, then let x transferred over its parent heavy chain
This process is repeated until the full path between the x y operation
This process is the process of finding x, y LCA's
int LCA( int x ,int y ){ int fx = top[x] ,fy = top[y]; while( fx != fy ){ if( dep[x] < dep[y] )swap(x ,y) ,swap( fx ,fy ); x= fa[fx] ,fx = top[x]; } return dep[x] < dep[y] ? x : y ; }
int c_query( int x ,int y ){ int fx = top[x] ,fy = top[y]; int ans = 0; while( fx != fy ){ if( dep[fx] < dep[fy] )swap(x ,y) ,swap(fx ,fy); ans += query( 1 ,dfn[fx] ,dfn[x] ); x = fa[x] ,fx = top[x]; } if( x==y )return ans; if( dfn[x] > dfn[y] )swap( x ,y ); if(dfn[x] != dfn[y])ans += query( 1 ,dfn[son[x]] ,dfn[y] ); return ans ; }
Segment tree: the tree-line on split chain code segment tree structure mostly written in the form of:
struct Tree{ int left ,right; int t ,lazy; }tree[N<<2];
Is this faster? I do not understand (the problem may never get to know me
Template question: HDU 3966 Aragorn's Story
Modify the interval, a single point of inquiry
I am useless in this segment tree structure also had to write
#include<bits/stdc++.h> #define fi first #define se second #define rep( i ,x ,y ) for( int i= x; i<= y ;i++ ) #define reb( i ,y ,x ) for( int i= y; i>= x ;i-- ) #define mem( a ,x ) memset( a ,x ,sizeof(a)) #define lson pos<<1 ,l ,m #define rson pos<<1|1 ,m+1 ,r using namespace std; typedef long long ll; typedef long double ld; typedef pair<int ,int> pii; typedef pair<ll ,ll> pll; typedef pair<string ,int> psi; const int inf = 0x3f3f3f3f; const int N = 50005; const int M = 1000005; struct Edge{ int next ,to; }edge[N<<2]; int sz[N] ,top[N] ,son[N] ,dep[N]; int fa[N] ,dfn[N] ,rnk[N]; int m ,n ,q ,tot = 0 ,cnt = 0 ,k; int head[N] ; ll val[N<<2] ,tree[N<<4] ,lazy[N<<4]; //线段树部分 void build( int pos ,int l ,int r ){ if( l== r){ tree[pos] = val[ rnk[l] ]; return; } int m = (l+r)>>1; build ( rson ); build ( lson ); tree[pos] = tree[pos<<1]+tree[pos<<1|1]; return; } void push_down( int pos ){ int lc = pos<<1 ,rc = pos<<1|1 ; tree[lc] += lazy[pos]; tree[rc] += lazy[pos]; lazy[lc] += lazy[pos]; lazy[rc] += lazy[pos]; lazy[pos] = 0; return; } void updata( int pos ,int l, int r ,int L ,int R ,int k ){ //cout<<" updata "<<l<<" "<<r<<" "<<L<<" "<<R <<" "<<k<<endl; if( L<=l && r<=R ){ lazy[pos] += k; tree[pos] += k; return; } int m = ( l+r )>>1; if( L <= m )updata( lson ,L ,R ,k); if( R > m )updata( rson ,L ,R ,k); tree[pos] = tree[pos>>1] + tree[pos>>1|1]; return; } ll query( int pos ,int l ,int r ,int L ,int R ){ //cout<<" query "<<l<<" "<<r<<" " <<L <<" "<<R<<endl; if( L<=l && r <= R ) return tree[pos]; ll ans=0; push_down( pos ); int m =( l+r )>>1; if( L <=m )ans += query( lson ,L ,R ); if( R > m )ans += query( rson ,L ,R ); return ans; } //树链剖分部分 --dfs1 ,dfs2 ,query ,updata void dfs1( int u ,int rt ,int d ){ //cout<<" dfs1 "<<u<<" "<<rt<<" dep "<<d<<endl; dep[u] = d; fa[u] = rt; sz[u] = 1; for( int i = head[u]; i ;i = edge[i].next ){ int v =edge[i] .to; if( v == fa[u] )continue; dfs1( v ,u ,d+1 ); sz[u] += sz[v]; if( son[u] == 0 || sz[v] >sz[ son[u]]){ son[u] = v; } } return ; } void dfs2( int u ,int t ){ // u : now t :top //cout<<" dfs2 "<<u<<" "<<t<<" son "<<son[u]<<endl; top[u] = t; dfn[u] = ++cnt; rnk[cnt] = u; if( !son[u] ){ return ; } dfs2( son[u] ,t ); for( int i = head[u]; i ; i = edge[i].next ){ int v= edge[i].to; if( v == son[u] || v == fa[u] )continue; dfs2 (v, v); } } ll query_path( int x ,int y){ ll ans = 0; int fx = top[x] ,fy = top[y]; //cout<<" query_p "<<x <<" "<<y<<" "<<fx<<" "<<fy<<endl; while( fx != fy ){ if(dep[fx] >= dep[fy] ){ ans += query( 1 ,1 ,n ,dfn[fx] ,dfn[x] ); x = fa[fx] ; } else { ans += query( 1 ,y]);, N, Dfn [Fy], Dfn [1 y = fa[fy]; } fx = top[x] ,fy = top[y]; } if(x != y ){ if( dfn[x] < dfn[y] ){ ans += query(1 ,1 ,n,dfn[x] ,dfn[y] ); } else { ans += query(1 ,1 ,n,dfn[y] ,dfn[x] ); } } else ans += query( 1 ,1 ,n,dfn[x] ,dfn[y] ); return ans; } void updata_path( int x ,int y ,int z ){ //cout<<x<<y<<z<<endl; int fx = top[x] ,fy = top[y]; //cout<<" updata_p "<<x <<" "<<y<<" "<<fx<<" "<<fy<<endl; while( fx != fy ){ if( dep[fx] >= dep[fy] ){ updata( 1 ,1 ,n ,dfn[fx] ,dfn[x] ,z); x = fa[fx];1,1 updata ({Else } ,n ,dfn[fy] ,dfn[y] ,z); y = fa[fy]; } fx = top[x] ,fy = top[y]; } if( x!=y ){ if( dfn[x] < dfn[y] )updata( 1 ,1 ,n ,dfn[x] ,dfn[y] ,z ); else updata( 1 ,1 ,n ,dfn[y] ,dfn[x] ,z ); } else updata( 1 ,1 , n, dfn[x] ,dfn[y] ,z); } int main( ){ while( ~ scanf("%d%d%d" ,&n ,&m ,&q) ){ cnt = tot = 0; mem( son ,0 ); mem( tree ,0); mem( lazy ,0); rep( i ,1 ,n )scanf("%lld" ,&val[i] ) ,head[i] = edge[i].next = 0; int l ,r; while( m-- ){ scanf("%d%d" ,&l ,&r ); edge[++tot].next = head[l]; edge[tot].to = r; head[l] = tot; edge[++tot].next = head[r]; edge[tot].to = l; head[r] = tot; } dfs1( 1 ,1 ,0 ); dfs2( 1 ,1 ); build(1, 1 ,n ); char op; while ( q--){ //cout<<q<<endl; cin>>op; if( op == 'I' ){ scanf("%d%d%d" ,&l ,&r ,&k); updata_path( l ,r ,k ); } if( op == 'Q' ){ scanf("%d" ,&l ); printf("%lld\n" ,query(1 ,1 ,n ,dfn[ l ] ,dfn[ l ] ) ); } if( op == 'D' ){ scanf("%d%d%d" ,&l ,&r ,&to); //cout<<l<<" "<<r<<" "<<k<<endl; updata_path( l ,r ,-k ); } } } return 0; }