#include<bits/stdc++.h>
using namespace std;
#define ljl long long
#define lc p<<1
#define rc p<<1|1
const ljl N=3e4+5,inf=1e18;
ljl n,u,v,q,cnt_e,head[N<<1],cnt_dfn,rnk[N];
string s;
struct E{
ljl from,to,pre;
}e[N<<2];
void add(ljl from,ljl to)
{
e[++cnt_e].from=from;
e[cnt_e].to=to;
e[cnt_e].pre=head[from];
head[from]=cnt_e;
return;
}
struct NODE{
ljl w,fa,dep,siz,hson,tp,dfn;
}node[N];
struct SMT{
ljl l,r,sum,maxn;
}tree[N<<2];
struct OPTSMT{
void build(ljl l,ljl r,ljl p)
{
tree[p].l=l;tree[p].r=r;
if(l==r)
{
tree[p].sum=tree[p].maxn=node[rnk[l]].w;
return;
}
ljl mid=l+r>>1;
build(l,mid,lc);
build(mid+1,r,rc);
tree[p].maxn=max(tree[lc].maxn,tree[rc].maxn);
tree[p].sum=tree[lc].sum+tree[rc].sum;
return;
}
ljl querymax(ljl s,ljl t,ljl p)
{
if(s<=tree[p].l&&t>=tree[p].r)
return tree[p].maxn;
ljl mid=tree[p].l+tree[p].r>>1;
return max(querymax(s,t,lc),querymax(s,t,rc));
}
ljl querysum(ljl s,ljl t,ljl p)
{
if(s<=tree[p].l&&tree[p].r<=t)
return tree[p].sum;
ljl mid=tree[p].l+tree[p].r>>1;
return querysum(s,t,lc)+querysum(s,t,rc);
}
void upd(ljl x,ljl val,ljl p)
{
if(tree[p].l==tree[p].r)
{
tree[p].sum=tree[p].maxn=val;
return;
}
ljl mid=tree[p].l+tree[p].r>>1;
if(x<=mid)
upd(x,val,lc);
else
upd(x,val,rc);
tree[p].sum=tree[lc].sum+tree[rc].sum;
tree[p].maxn=max(tree[lc].maxn,tree[rc].maxn);
return;
}
}solve;
void dfs1(ljl u)
{
node[u].hson=-1;
node[u].siz=1;
for(ljl i=head[u];i;i=e[i].pre)
{
ljl v=e[i].to;
if(!node[v].dep)
{
node[v].dep=node[u].dep+1;
node[v].fa=u;
dfs1(v);
node[u].siz+=node[v].siz;
if(node[u].hson==-1||node[v].siz>node[node[u].hson].siz)
node[u].hson=v;
}
}
return;
}
void dfs2(ljl u,ljl t)
{
node[u].tp=t;
++cnt_dfn;
node[u].dfn=cnt_dfn;
rnk[cnt_dfn]=u;
if(node[u].hson==-1)
return;
dfs2(node[u].hson,t);
for(ljl i=head[u];i;i=e[i].pre)
{
if(e[i].to!=node[u].fa&&e[i].to!=node[u].hson)
dfs2(e[i].to,e[i].to);
}
return;
}
ljl querymax(ljl x,ljl y)
{
ljl fx=node[x].tp,fy=node[y].tp,ret=-inf;
while(fx!=fy)
{
if(node[fx].dep>=node[fy].dep)
ret=max(ret,solve.querymax(node[fx].dfn,node[x].dfn,1)),x=node[fx].fa;
else
ret=max(ret,solve.querymax(node[fy].dfn,node[y].dfn,1)),y=node[fy].fa;
fx=node[x].tp;fy=node[y].tp;
}
if(node[x].dfn<node[y].dfn)
ret=max(ret,solve.querymax(node[x].dfn,node[y].dfn,1));
else
ret=max(ret,solve.querymax(node[y].dfn,node[x].dfn,1));
return ret;
}
ljl querysum(ljl x,ljl y)
{
ljl fx=node[x].tp,fy=node[y].tp,ret=0;
while(fx!=fy)
{
if(node[fx].dep>=node[fy].dep)
ret=solve.querysum(node[fx].dfn,node[x].dfn,1),x=node[fx].fa;
else
ret=solve.querysum(node[fy].dfn,node[y].dfn,1),y=node[fy].fa;
fx=node[x].tp;fy=node[y].tp;
}
if(node[x].dfn<node[y].dfn)
ret+=solve.querysum(node[x].dfn,node[y].dfn,1);
else
ret+=solve.querysum(node[y].dfn,node[x].dfn,1);
return ret;
}
int main(){
scanf("%lld",&n);
for(ljl i=1;i<n;i++)
{
scanf("%lld%lld",&u,&v);
add(u,v);add(v,u);
}
for(ljl i=1;i<=n;i++)
scanf("%lld",&node[i].w);
node[1].dep=1;
dfs1(1);
dfs2(1,1);
solve.build(1,n,1);
scanf("%lld",&q);
while(q--)
{
cin>>s;
scanf("%lld%lld",&u,&v);
if(s=="CHANGE")
solve.upd(node[u].dfn,v,1);
if(s=="QMAX")
printf("%lld\n",querymax(u,v));
if(s=="QSUM")
printf("%lld\n",querysum(u,v));
}
return 0;
}