BZOJ 1036 [ZJOI2008]树的统计Count
以前动态树写过这个题,今天尝试树链剖分解决~
模板题,就声明一点,线段树维护的是点权
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
没有人能阻止我前进的步伐,除了我自己!