//Problem: 1036 Time Limit: 10 Sec Memory Limit: 162 MB
// Time:2508 ms Memory:5080 kb
#include<cstdio>
#include<cstring>
#include<algorithm>
#define m(a,b) memset(a,b,sizeof a)
using namespace std;
const int N=3e4+5,INF=0x3f3f3f3f;
int head[N],tot,ovo,n;
int top[N],fa[N],dep[N],sz[N],p[N],fp[N],son[N];
struct Edge{int to,nex;}edge[N<<1];
void add(int from,int to){
edge[++tot]=(Edge){to,head[from]};head[from]=tot;
edge[++tot]=(Edge){from,head[to]};head[to]=tot;
}
void route(int x){
sz[x]=1;
for(int i=head[x];i;i=edge[i].nex){
int y=edge[i].to;
if(y==fa[x]) continue;
dep[y]=dep[x]+1,fa[y]=x;
route(y),sz[x]+=sz[y];
if(son[x]==-1||sz[y]>sz[son[x]]) son[x]=y;
}
}
void getpos(int x,int root){
top[x]=root,p[x]=++ovo,fp[ovo]=x;
if(son[x]==-1) return;
getpos(son[x],root);
for(int i=head[x];i;i=edge[i].nex){
int y=edge[i].to;
if(y!=fa[x]&&y!=son[x]) getpos(y,y);
}
}
int mmax[N<<2],sum[N<<2],c[N];
void build(int l,int r,int pos){
if(l==r){
mmax[pos]=sum[pos]=c[fp[l]];
return;
}
int mid=(l+r)>>1;
build(l,mid,pos<<1);
build(mid+1,r,pos<<1|1);
mmax[pos]=max(mmax[pos<<1],mmax[pos<<1|1]);
sum[pos]=sum[pos<<1]+sum[pos<<1|1];
}
void chanpoint(int n,int val,int l,int r,int pos){
if(l==r){
mmax[pos]=sum[pos]=val;
return;
}
int mid=(l+r)>>1;
if(n<=mid) chanpoint(n,val,l,mid,pos<<1);
else chanpoint(n,val,mid+1,r,pos<<1|1);
mmax[pos]=max(mmax[pos<<1],mmax[pos<<1|1]);
sum[pos]=sum[pos<<1]+sum[pos<<1|1];
}
int querymax(int cl,int cr,int l,int r,int pos){
if(cl<=l&&r<=cr) return mmax[pos];
int ans=-INF,mid=(l+r)>>1;
if(cl<=mid) ans=max(ans,querymax(cl,cr,l,mid,pos<<1));
if(cr>mid) ans=max(ans,querymax(cl,cr,mid+1,r,pos<<1|1));
return ans;
}
int querysum(int cl,int cr,int l,int r,int pos){
if(cl<=l&&r<=cr) return sum[pos];
int ans=0,mid=(l+r)>>1;
if(cl<=mid) ans+=querysum(cl,cr,l,mid,pos<<1);
if(cr>mid) ans+=querysum(cl,cr,mid+1,r,pos<<1|1);
return ans;
}
int findmax(int x,int y){
int f1=top[x],f2=top[y],ans=-INF;
while(f1!=f2){
if(dep[f1]<dep[f2])
swap(x,y),swap(f1,f2);
ans=max(ans,querymax(p[f1],p[x],1,n,1));
x=fa[f1],f1=top[x];
}
if(dep[x]>dep[y]) swap(x,y);
return max(ans,querymax(p[x],p[y],1,n,1));
}
int findsum(int x,int y){
int f1=top[x],f2=top[y],ans=0;
while(f1!=f2){
if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2);
ans+=querysum(p[f1],p[x],1,n,1);
x=fa[f1],f1=top[x];
}
if(dep[x]>dep[y]) swap(x,y);
return ans+=querysum(p[x],p[y],1,n,1);
}
char s[7];
int main(){
//m(head,0),,tot=0,ovo=0;
m(son,-1);
scanf("%d",&n);int q,a,b;
for(int i=1;i<=n-1;i++)
scanf("%d%d",&a,&b),add(a,b);
dep[1]=0,fa[1]=-1,route(1);getpos(1,1);
for(int i=1;i<=n;i++) scanf("%d",&c[i]);
build(1,n,1);
scanf("%d",&q);
while(q--){
scanf("%s%d%d",s,&a,&b);
if(s[1]=='H') chanpoint(p[a],b,1,n,1);
if(s[1]=='M') printf("%d\n",findmax(a,b));
if(s[1]=='S') printf("%d\n",findsum(a,b));
}
}
BZOJ-1036-(树链剖分+线段树 模板)
最新推荐文章于 2019-07-12 10:15:00 发布