//树链剖分,线段树维护 #include <iostream> #include <cstdio> #define maxn 300500 #define INF 0x3f3f3f3f using namespace std; int n,m; int head[maxn],cnt; int dep[maxn],son[maxn],siz[maxn],fa[maxn]; int top[maxn],seg[maxn],rnk[maxn],tot; int maxx[maxn],sum[maxn]; int a[maxn]; char ch; struct EDGE { int next,to; }edge[maxn]; void add(int u,int v) { edge[++cnt].next=head[u]; edge[cnt].to=v; head[u]=cnt; } void dfs1(int root) { son[root]=0; siz[root]=1; for(int i=head[root];i;i=edge[i].next) { int v=edge[i].to; if(v==fa[root])continue; dep[v]=dep[root]+1; fa[v]=root; dfs1(v); if(siz[son[root]]<siz[v])son[root]=v; siz[root]+=siz[v]; } } void dfs2(int root,int tp) { top[root]=tp;seg[root]=++tot;rnk[tot]=root; if(son[root])dfs2(son[root],tp); for(int i=head[root];i;i=edge[i].next) { int v=edge[i].to; if(v==fa[root]||v==son[root])continue; dfs2(v,v); } } void build(int k,int l,int r) { if(l==r) { maxx[k]=sum[k]=a[rnk[l]]; return; } int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); sum[k]=sum[k<<1]+sum[k<<1|1]; maxx[k]=max(maxx[k<<1],maxx[k<<1|1]); } void update(int k,int l,int r,int x,int v) { if(l==r) { maxx[k]=sum[k]=v; return; } int mid=(l+r)>>1; if(x<=mid)update(k<<1,l,mid,x,v); else update(k<<1|1,mid+1,r,x,v); sum[k]=sum[k<<1]+sum[k<<1|1]; maxx[k]=max(maxx[k<<1],maxx[k<<1|1]); } int querysum(int k,int l,int r,int x,int y) { if(x<=l&&y>=r) { return sum[k]; } int mid=(l+r)>>1; int res=0; if(x<=mid)res+=querysum(k<<1,l,mid,x,y); if(y>mid)res+=querysum(k<<1|1,mid+1,r,x,y); return res; } int querymax(int k,int l,int r,int x,int y) { if(x<=l&&y>=r) { return maxx[k]; } if(y<l||x>r)return -INF; int mid=(l+r)>>1; return max(querymax(k<<1,l,mid,x,y),querymax(k<<1|1,mid+1,r,x,y)); } int query_Max_tree(int k,int l,int r,int u,int v) { int fu=top[u],fv=top[v]; int ans=-INF; while(fu!=fv) { if(dep[fu]<dep[fv]) { swap(fu,fv); swap(u,v); } ans=max(ans,querymax(1,1,n,seg[fu],seg[u])); u=fa[fu]; fu=top[u]; } if(dep[u]<dep[v])swap(u,v); ans=max(ans,querymax(1,1,n,seg[v],seg[u])); return ans; } int query_Sum_tree(int k,int l,int r,int u,int v) { int fu=top[u],fv=top[v]; int ans=0; while(fu!=fv) { if(dep[fu]<dep[fv]) { swap(fu,fv); swap(u,v); } ans+=querysum(1,1,n,seg[fu],seg[u]); u=fa[fu]; fu=top[u]; } if(dep[u]<dep[v])swap(u,v); ans+=querysum(1,1,n,seg[v],seg[u]); return ans; } int main() { scanf("%d",&n); for(int i=1;i<=n-1;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v);add(v,u); } for(int i=1;i<=n;i++)scanf("%d",&a[i]); dep[1]=1;dfs1(1);dfs2(1,1); build(1,1,n); scanf("%d",&m); for(int i=1;i<=m;i++) { char op[10]; int u,v; scanf("%s%d%d",op,&u,&v); if(op[0]=='C')update(1,1,n,seg[u],v); else if(op[1]=='M')printf("%d\n",query_Max_tree(1,1,n,u,v)); else printf("%d\n",query_Sum_tree(1,1,n,u,v)); } //ch=getchar(); return 0; }