#include<bits/stdc++.h>
#define max(a,b) a>b?a:b
#define swap(a,b) a^=b^=a^=b
#define update(x) t[x]=t[x<<1]+t[x<<1|1]
using namespace std;
const int N=3e4+5;
vector<int>G[N];
int a[N];
int n,x,y,q;
string opt;
inline int read()
{
int x(0);char c(0);bool flag(0);
for(;!isdigit(c);c=getchar())if(c=='-')flag=1;
for(;isdigit(c);c=getchar()) x=(x<<1)+(x<<3)+(c^48);
return flag?-x:x;
}
namespace Subdivision
{
int fa[N],son[N],val[N],id[N],top[N],dep[N],siz[N],tot=0;
void dfs1(int u,int father)
{
dep[u]=dep[father]+1;
fa[u]=father;
siz[u]=1;
for(int v:G[u])
{
if(!dep[v]&&v!=father)
{
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u,int t)
{
top[u]=t;
id[u]=++tot;
val[tot]=a[u];
if(!son[u])return;
dfs2(son[u],t);
for(int v:G[u])
{
if(v!=son[u]&&v!=fa[u])
{
dfs2(v,v);
}
}
}
}
using namespace Subdivision;
namespace SegmentTree
{
struct Node
{
int l,r,len,sum,maxx;
Node operator +(Node x)
{
Node t;
t={l,x.r,len+x.len,sum+x.sum,max(maxx,x.maxx)};
return t;
}
}t[N<<2];
void build(int now,int l,int r)
{
if(l==r)
{
t[now]={l,r,1,val[l],val[l]};
return;
}
int mid=l+r>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
update(now);
}
void modify(int now,int pos,int x)
{
if(t[now].l==t[now].r)
{
t[now].sum=t[now].maxx=x;
return;
}
int mid=t[now].l+t[now].r>>1;
if(pos<=mid) modify(now<<1,pos,x);
if(pos>mid) modify(now<<1|1,pos,x);
update(now);
}
Node query(int now,int x,int y)
{
if(t[now].l==t[now].r) return t[now];
int mid=t[now].l+t[now].r>>1;
if(x<=mid&&y>mid) return query(now<<1,x,y)+query(now<<1|1,x,y);
if(x<=mid) return query(now<<1,x,y);
if(y>mid) return query(now<<1|1,x,y);
}
}
inline int Qmax(int x,int y)
{
int ans=-0x3f3f3f3f,tmp;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
tmp=SegmentTree::query(1,id[top[x]],id[x]).maxx;
ans=max(ans,tmp);
x=fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
tmp=SegmentTree::query(1,id[x],id[y]).maxx;
ans=max(ans,tmp);
return ans;
}
inline int Qsum(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans+=SegmentTree::query(1,id[top[x]],id[x]).sum;
x=fa[top[x]];
}
if(id[x]>id[y]) swap(x,y);
ans+=SegmentTree::query(1,id[x],id[y]).sum;
return ans;
}
void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int main()
{
n=read();
for(int i=1;i<n;i++)
{
x=read();y=read();
G[x].push_back(y);
G[y].push_back(x);
}
for(int i=1;i<=n;i++) a[i]=read();
dfs1(1,0);
dfs2(1,1);
SegmentTree::build(1,1,n);
q=read();
while(q--)
{
cin>>opt;
x=read();y=read();
if(opt=="CHANGE")
{
SegmentTree::modify(1,id[x],y);
}
else if(opt=="QMAX")
{
write(Qmax(x,y));
putchar('\n');
}
else
{
write(Qsum(x,y));
putchar('\n');
}
}
return 0;
}