单点修改,询问链最大,链和,LCT和树链剖分都可以写,不过LCT就是慢....
LCT:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=30010;
int n,m,u[maxn],v[maxn];char s[7];
struct LCT{
int val[maxn],fa[maxn],c[maxn][2],sum[maxn],maxs[maxn],rev[maxn];
bool isroot(int x){return (c[fa[x]][0]!=x)&&(c[fa[x]][1]!=x);}
void flip(int x){swap(c[x][0],c[x][1]),rev[x]^=1;}
void update(int x){
int ls=c[x][0],rs=c[x][1];
sum[x]=maxs[x]=val[x];
if (ls) sum[x]+=sum[ls],maxs[x]=max(maxs[x],maxs[ls]);
if (rs) sum[x]+=sum[rs],maxs[x]=max(maxs[x],maxs[rs]);
}
void down(int x){if (rev[x]) flip(c[x][0]),flip(c[x][1]),rev[x]^=1;}
void relax(int x){if (!isroot(x)) relax(fa[x]);down(x);}
int which(int x){return c[fa[x]][1]==x;}
void rotate(int x){
int y=fa[x],z=fa[y],nx=which(x),ny=which(y);
fa[c[x][!nx]]=y,c[y][nx]=c[x][!nx];
fa[x]=z;if (!isroot(y)) c[z][ny]=x;
fa[y]=x,c[x][!nx]=y;update(y);
}
void splay(int x){
relax(x);
while (!isroot(x)){
if (isroot(fa[x])) rotate(x);
else if (which(x)==which(fa[x])) rotate(fa[x]),rotate(x);
else rotate(x),rotate(x);
}
update(x);
}
void access(int x){for (int p=0;x;x=fa[x]) splay(x),fa[c[x][1]=p]=x,update(x),p=x;}
void makeroot(int x){access(x),splay(x),flip(x),update(x);}
void modify(int x,int v){val[x]=v,splay(x);}
void link(int a,int b){makeroot(a),fa[a]=b;}
void qmax(int a,int b){makeroot(a),access(b),splay(b),printf("%d\n",maxs[b]);}
void qsum(int a,int b){makeroot(a),access(b),splay(b),printf("%d\n",sum[b]);}
}T;
int main(){
scanf("%d",&n);
for (int i=1;i<n;i++) scanf("%d%d",&u[i],&v[i]);
for (int i=1,a;i<=n;i++) scanf("%d",&a),T.modify(i,a);
for (int i=1;i<n;i++) T.link(u[i],v[i]);
scanf("%d",&m);
for (int i=1,a,b;i<=m;i++){
scanf("%s%d%d",s,&a,&b);
if (s[0]=='C') T.modify(a,b);
else if (s[1]=='S') T.qsum(a,b);
else T.qmax(a,b);
}
return 0;
}