【ZJOI2008】【BZOJ1036】树的统计-树链剖分
做的第一道树链剖分的题,树链剖分学习。
线段树维护重边就很简单了,单点修改,区间查询最大,区间求和,所以直接贴代码。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <vector> 6 7 using namespace std; 8 9 const int N = 30000 + 5; 10 const int INF = 1<<30; 11 12 vector <int> G[N]; 13 int n, q, num, a, b, w[N]; 14 int id[N], fa[N], val[N], son[N], top[N], size[N], deep[N]; 15 16 namespace SGT{ 17 #define root 1,1,num 18 #define lson rt<<1,L,mid 19 #define rson rt<<1|1,mid+1,R 20 int Sum[N<<2], Max[N<<2]; 21 void pushup( int rt ){ 22 Sum[rt] = Sum[rt<<1] + Sum[rt<<1|1]; 23 Max[rt] = max( Max[rt<<1],Max[rt<<1|1] ); 24 } 25 void Build( int rt, int L, int R ){ 26 if ( L == R ){ 27 Sum[rt] = Max[rt] = val[L]; 28 return; 29 } 30 int mid = (L+R)>>1; 31 Build( lson ); 32 Build( rson ); 33 pushup( rt ); 34 } 35 void update( int rt, int L, int R, int p, int qv ){ 36 if ( L == R ){Sum[rt] = Max[rt] = qv;return;} 37 int mid = (L+R)>>1; 38 if ( p <= mid ) update( lson,p,qv ); 39 if ( p > mid ) update( rson,p,qv ); 40 pushup( rt ); 41 } 42 int Qmax( int rt, int L, int R, int ql, int qr ){ 43 if ( ql <= L && R <= qr ) return Max[rt]; 44 int mid = (L+R)>>1, ret = -INF; 45 if ( ql <= mid ) ret = max( ret,Qmax(lson,ql,qr) ); 46 if ( qr > mid ) ret = max( ret,Qmax(rson,ql,qr) ); 47 return ret; 48 } 49 int Qsum( int rt, int L, int R, int ql, int qr ){ 50 if ( ql <= L && R <= qr ) return Sum[rt]; 51 int mid = (L+R)>>1, ret = 0; 52 if ( ql <= mid ) ret += Qsum(lson,ql,qr); 53 if ( qr > mid ) ret += Qsum(rson,ql,qr); 54 return ret; 55 } 56 } 57 namespace TL{ 58 void dfs1( int u, int d ){ 59 son[u] = 0; 60 size[u] = 1; 61 deep[u] = d; 62 for ( int i = 0; i < G[u].size(); i ++ ) 63 if ( G[u][i] != fa[u] ){ 64 int v = G[u][i]; 65 fa[v] = u; 66 dfs1( v,d+1 ); 67 size[u] += size[v]; 68 if ( size[v] > size[son[u]] ) son[u] = v; 69 } 70 } 71 void dfs2( int u, int tp ){ 72 id[u] = ++num; 73 top[u] = tp; 74 if ( son[u] ) dfs2( son[u],tp ); 75 for ( int i = 0; i < G[u].size(); i ++ ){ 76 int v = G[u][i]; 77 if ( v != fa[u] && v != son[u] ) dfs2( v,v ); 78 } 79 } 80 int Qmax( int u, int v ){ 81 int ret = -INF, t1 = top[u], t2 = top[v]; 82 while ( t1 != t2 ){ 83 if ( deep[t1] < deep[t2] ) 84 swap(t1,t2),swap(u,v); 85 ret = max( ret,SGT::Qmax(root,id[t1],id[u]) ); 86 u = fa[t1], t1 = top[u]; 87 } 88 if ( deep[u] > deep[v] ) swap(u,v); 89 return max( ret,SGT::Qmax(root,id[u],id[v]) ); 90 } 91 int Qsum( int u, int v ){ 92 int ret = 0, t1 = top[u], t2 = top[v]; 93 while ( t1 != t2 ){ 94 if ( deep[t1] < deep[t2] ) 95 swap(t1,t2), swap(u,v); 96 ret += SGT::Qsum(root,id[t1],id[u]); 97 u = fa[t1], t1 = top[u]; 98 } 99 if ( deep[u] > deep[v] ) swap(u,v); 100 return ret + SGT::Qsum(root,id[u],id[v]); 101 } 102 } 103 void data(){ 104 scanf( "%d", &n ); 105 for ( int i = 2; i <= n; i ++ ){ 106 scanf( "%d%d", &a, &b ); 107 G[a].push_back(b); 108 G[b].push_back(a); 109 } 110 num = 0; 111 TL :: dfs1( 1,1 ); 112 TL :: dfs2( 1,1 ); 113 for ( int i = 1; i <= n; i ++ ) 114 scanf( "%d", &w[i] ); 115 for ( int i = 1; i <= n; i ++ ) 116 val[id[i]] = w[i]; 117 SGT :: Build(root); 118 } 119 void solve(){ 120 char op[10]; 121 scanf( "%d", &q ); 122 for ( int i = 1; i <= q; i ++ ){ 123 scanf( "%s%d%d", op, &a, &b ); 124 if ( op[1] == 'M' ) printf( "%d\n", TL::Qmax(a,b) ); 125 if ( op[1] == 'S' ) printf( "%d\n", TL::Qsum(a,b) ); 126 if ( op[0] == 'C' ) SGT::update(root,id[a],b); 127 } 128 } 129 int main(){ 130 data(); 131 solve(); 132 return 0; 133 }