第一次写树链剖分。。昨天晚上看到JMCDY(%%%)在不屑地写这道题,我便写了一波。
dfs的时候top的位置写错了。。。找了好久,迷之错误。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=30005,inf=0x3f3f3f3f;
int Max[maxn*4],val[maxn*4],Maxans,Sumans;
void maintain(int p,int u,int v){
Max[p]=max(Max[u],Max[v]);
val[p]=val[u]+val[v];
}
void update(int p,int l,int r,int pos,int w){
if((l==pos)&&(r==pos)){
Max[p]=val[p]=w;
return;
}
int mid=(l+r)>>1,u=p<<1,v=u+1;
if(pos<=mid)update(u,l,mid,pos,w);
else update(v,mid+1,r,pos,w);
maintain(p,u,v);
}
void query(int p,int l,int r,int L,int R){
if((l==L)&&(r==R)){
Maxans=max(Maxans,Max[p]);
Sumans+=val[p];
return;
}
int mid=(l+r)>>1,u=p<<1,v=u+1;
if(R<=mid)query(u,l,mid,L,R);
else if(L>mid)query(v,mid+1,r,L,R);
else{
query(u,l,mid,L,mid);
query(v,mid+1,r,mid+1,R);
}
}
int tmp[maxn],Begin[maxn],Next[maxn*2],to[maxn*2],e;
int id[maxn],fa[maxn],dep[maxn],top[maxn],sz[maxn],Mson[maxn],tot,n;
void add(int u,int v){
to[++e]=v,Next[e]=Begin[u],Begin[u]=e;
}
void create(int u){
sz[u]=1;
for(int i=Begin[u];i;i=Next[i]){
int v=to[i];
if(v==fa[u])
continue;
dep[v]=dep[u]+1;
fa[v]=u;
create(v);
sz[u]+=sz[v];
if(sz[v]>sz[Mson[u]])
Mson[u]=v;
}
}
void dfs(int u){
id[u]=++tot;
update(1,1,n,id[u],tmp[u]);
if(!Mson[u])
return;
top[Mson[u]]=top[u];
dfs(Mson[u]);
for(int i=Begin[u];i;i=Next[i]){
int v=to[i];
if(id[v])
continue;
top[v]=v;
dfs(v);
}
}
void solve(int u,int v){
Maxans=-inf;
Sumans=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])
swap(u,v);
query(1,1,n,id[top[u]],id[u]);
u=fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);
query(1,1,n,id[u],id[v]);
}
int main(){
int m,u,v;
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
for(int i=1;i<=n;i++)
scanf("%d",&tmp[i]);
dep[1]=1;
top[1]=1;
create(1);
dfs(1);
char ch[10];
scanf("%d",&m);
while(m--){
scanf("%s%d%d",ch,&u,&v);
if(ch[1]=='H')
update(1,1,n,id[u],v);
else{
solve(u,v);
int ans=(ch[1]=='M')?Maxans:Sumans;
printf("%d\n",ans);
}
}
return 0;
}