以前动态树写过这个题,今天尝试树链剖分解决~
模板题,就声明一点,线段树维护的是点权
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 7 #define N 50000 8 #define M 100000 9 #define INF 1e9 10 11 using namespace std; 12 13 int head[N],to[M],next[M]; 14 int sz[N],top[N],bh[N],fa[N],son[N],dep[N]; 15 int sum[N<< 2 ],mx[N<< 2 ],val[N],dat[N]; 16 int q[N]; 17 int n,cnt,tot,qu; 18 19 inline void add( int u, int v) 20 { 21 to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++ ; 22 } 23 24 inline void prep() 25 { 26 int h= 1 ,t= 2 ,sta; 27 q[ 1 ]= 1 ; dep[ 1 ]= 1 ; 28 while (h< t) 29 { 30 sta=q[h++]; sz[sta]= 1 ; 31 for ( int i=head[sta];~i;i= next[i]) 32 if (to[i]!= fa[sta]) 33 { 34 fa[to[i]]= sta; 35 dep[to[i]]=dep[sta]+ 1 ; 36 q[t++]= to[i]; 37 } 38 } 39 for ( int j=t- 1 ;j>= 1 ;j-- ) 40 { 41 sta= q[j]; 42 for ( int i=head[sta];~i;i= next[i]) 43 if (to[i]!= fa[sta]) 44 { 45 sz[sta]+= sz[to[i]]; 46 if (sz[to[i]]>sz[son[sta]]) son[sta]= to[i]; 47 } 48 } 49 for ( int i= 1 ;i<t;i++ ) 50 { 51 sta= q[i]; 52 if (son[fa[sta]]==sta) top[sta]=top[fa[sta]]; // 不是重链顶部 53 else top[sta]= sta; 54 } 55 } 56 57 inline void rewrite() 58 { 59 for ( int i= 1 ;i<=n;i++ ) 60 if (top[i]== i) 61 for ( int j=i;j;j=son[j]) // 每条重链的编号是连续的 62 { 63 bh[j]=++ tot; 64 dat[tot]= val[j]; 65 } 66 } 67 68 inline void pushup( int x) 69 { 70 sum[x]=sum[x<< 1 ]+sum[x<< 1 | 1 ]; 71 mx[x]=max(mx[x<< 1 ],mx[x<< 1 | 1 ]); 72 } 73 74 inline void build( int u, int L, int R) 75 { 76 if (L==R) {sum[u]=mx[u]=dat[L]; return ;} 77 int MID=(L+R)>> 1 ; 78 build(u<< 1 ,L,MID); build(u<< 1 | 1 ,MID+ 1 ,R); 79 pushup(u); 80 } 81 82 inline void read() 83 { 84 memset(head,- 1 , sizeof head); cnt= 0 ; 85 scanf( " %d " ,& n); 86 for ( int i= 1 ,a,b;i<n;i++ ) 87 { 88 scanf( " %d%d " ,&a,& b); 89 add(a,b); add(b,a); 90 } 91 for ( int i= 1 ;i<=n;i++) scanf( " %d " ,& val[i]); 92 prep(); 93 rewrite(); 94 build( 1 , 1 ,tot); 95 } 96 97 inline int querysum( int u, int L, int R, int l, int r) 98 { 99 if (l<=L&&R<=r) return sum[u]; 100 int MID=(L+R)>> 1 ,res= 0 ; 101 if (l<=MID) res+=querysum(u<< 1 ,L,MID,l,r); 102 if (MID<r) res+=querysum(u<< 1 | 1 ,MID+ 1 ,R,l,r); 103 return res; 104 } 105 106 inline int getsum( int x, int y) 107 { 108 int res= 0 ; 109 while (top[x]!= top[y]) 110 { 111 if (dep[top[x]]< dep[top[y]]) swap(x,y); 112 res+=querysum( 1 , 1 ,tot,bh[top[x]],bh[x]); 113 x= fa[top[x]]; 114 } 115 if (bh[x]> bh[y]) swap(x,y); 116 res+=querysum( 1 , 1 ,tot,bh[x],bh[y]); 117 return res; 118 } 119 120 inline int querymax( int u, int L, int R, int l, int r) 121 { 122 if (l<=L&&R<=r) return mx[u]; 123 int MID=(L+R)>> 1 ,res=- INF; 124 if (l<=MID) res=max(res,querymax(u<< 1 ,L,MID,l,r)); 125 if (MID<r) res=max(res,querymax(u<< 1 | 1 ,MID+ 1 ,R,l,r)); 126 return res; 127 } 128 129 inline int getmax( int x, int y) 130 { 131 int res=- INF; 132 while (top[x]!= top[y]) 133 { 134 if (dep[top[x]]< dep[top[y]]) swap(x,y); 135 res=max(res,querymax( 1 , 1 ,tot,bh[top[x]],bh[x])); 136 x= fa[top[x]]; 137 } 138 if (bh[x]> bh[y]) swap(x,y); 139 140 res=max(res,querymax( 1 , 1 ,tot,bh[x],bh[y])); 141 return res; 142 } 143 144 inline void updata( int u, int L, int R, int pos, int sp) 145 { 146 if (L==R) {mx[u]=sum[u]=sp; return ;} 147 int MID=(L+R)>> 1 ; 148 if (pos<=MID) updata(u<< 1 ,L,MID,pos,sp); 149 else updata(u<< 1 | 1 ,MID+ 1 ,R,pos,sp); 150 pushup(u); 151 } 152 153 inline void go() 154 { 155 scanf( " %d " ,& qu); 156 char str[ 10 ]; int a,b; 157 while (qu-- ) 158 { 159 scanf( " %s%d%d " ,str,&a,& b); 160 if (str[ 1 ]== ' S ' ) printf( " %d\n " ,getsum(a,b)); 161 else if (str[ 1 ]== ' M ' ) printf( " %d\n " ,getmax(a,b)); 162 else updata( 1 , 1 ,tot,bh[a],b); 163 } 164 } 165 166 int main() 167 { 168 read(); 169 go(); 170 return 0 ; 171 }