【ZJOI2008】【BZOJ1036】树的统计-树链剖分

做的第一道树链剖分的题,树链剖分学习

线段树维护重边就很简单了,单点修改,区间查询最大,区间求和,所以直接贴代码。

  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 }
View Code

 

posted @ 2016-03-02 15:20  羁旅  阅读(115)  评论(0编辑  收藏  举报