BZOJ 1036: [ZJOI2008]树的统计Count【树链剖分】
1036: [ZJOI2008]树的统计Count
【题目描述】
传送门
【题解】
裸的树链剖分。
代码如下
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 30005
using namespace std;
int n,m,a[MAXN],W[MAXN];
int Tre[MAXN<<2],MT[MAXN<<2],Add[MAXN<<2];
int cnt,Son[MAXN],Siz[MAXN],Fa[MAXN],ID[MAXN],Dep[MAXN],Top[MAXN];
struct Edge{
int tot,son[MAXN<<1],nxt[MAXN<<1],lnk[MAXN];
void Add(int x,int y){son[++tot]=y;nxt[tot]=lnk[x];lnk[x]=tot;}
}E;
void First(int x,int f,int D){
Siz[x]=1;Dep[x]=D;Fa[x]=f;
for(int j=E.lnk[x],NowSize=0;j;j=E.nxt[j])
if(E.son[j]^f){
First(E.son[j],x,D+1),Siz[x]+=Siz[E.son[j]];
if(Siz[E.son[j]]>NowSize) NowSize=Siz[E.son[j]],Son[x]=E.son[j];
}
}
void Second(int x,int T){
ID[x]=++cnt;Top[x]=T;W[cnt]=a[x];
if(!Son[x]) return;Second(Son[x],T);
for(int j=E.lnk[x];j;j=E.nxt[j])
if(!ID[E.son[j]]) Second(E.son[j],E.son[j]);
}
void Build(int x,int l,int r){
if(l==r){Tre[x]=MT[x]=W[l];return;}
int mid=(r+l)>>1;
Build(x<<1,l,mid);Build(x<<1|1,mid+1,r);
Tre[x]=Tre[x<<1]+Tre[x<<1|1];MT[x]=max(MT[x<<1],MT[x<<1|1]);
}
void Updata(int x,int l,int r,int k,int p){
if(l==r){Tre[x]=MT[x]=p;return;}
int mid=(r+l)>>1;
if(k<=mid) Updata(x<<1,l,mid,k,p);else Updata(x<<1|1,mid+1,r,k,p);
Tre[x]=Tre[x<<1]+Tre[x<<1|1];MT[x]=max(MT[x<<1],MT[x<<1|1]);
}
int Query_Sum(int x,int l,int r,int L,int R){
if(L<=l&&r<=R) return Tre[x];
int mid=(r+l)>>1,Sum=0;
if(L<=mid) Sum+=Query_Sum(x<<1,l,mid,L,R);
if(R>mid) Sum+=Query_Sum(x<<1|1,mid+1,r,L,R);
return Sum;
}
int Query_Max(int x,int l,int r,int L,int R){
if(L<=l&&r<=R) return MT[x];
int mid=(r+l)>>1,Sum=-1e9;
if(L<=mid) Sum=max(Query_Max(x<<1,l,mid,L,R),Sum);
if(R>mid) Sum=max(Query_Max(x<<1|1,mid+1,r,L,R),Sum);
return Sum;
}
int Ask_Sum(int x,int y){
int Sum=0;
while(Top[x]^Top[y]){
if(Dep[Top[x]]>Dep[Top[y]]) swap(x,y);
Sum+=Query_Sum(1,1,n,ID[Top[y]],ID[y]);y=Fa[Top[y]];
}
if(Dep[x]>Dep[y]) swap(x,y);
Sum+=Query_Sum(1,1,n,ID[x],ID[y]);
return Sum;
}
int Ask_Max(int x,int y){
int Sum=-1e9;
while(Top[x]^Top[y]){
if(Dep[Top[x]]>Dep[Top[y]]) swap(x,y);
Sum=max(Sum,Query_Max(1,1,n,ID[Top[y]],ID[y]));y=Fa[Top[y]];
}
if(Dep[x]>Dep[y]) swap(x,y);
Sum=max(Query_Max(1,1,n,ID[x],ID[y]),Sum);
return Sum;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("prob.in","r",stdin);
freopen("prob.out","w",stdout);
#endif
scanf("%d",&n);
for(int i=1;i<n;i++){
int x,y;scanf("%d%d",&x,&y);
E.Add(x,y);E.Add(y,x);
}
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
scanf("%d",&m);
First(1,0,1);Second(1,1);Build(1,1,n);
for(int i=1;i<=m;i++){
char ch[15];scanf("%s",ch);
int x,y;scanf("%d%d",&x,&y);
if(ch[1]=='M') printf("%d\n",Ask_Max(x,y));else
if(ch[1]=='S') printf("%d\n",Ask_Sum(x,y));else Updata(1,1,n,ID[x],y);
}
return 0;
}