#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e7;
int n;
char op[100],u,v;
int cnt;
struct Edge{
int to,next;
}edge[N];
int head[N];
void init()
{
memset(head,-1,sizeof(head));
cnt=0;
}
void add_edge(int u,int v)
{
edge[++cnt].to = v;
edge[cnt].next = head[u];
head[u]=cnt;
}
int fa[N],dep[N],siz[N],son[N];
int top[N],dfn[N],rnk[N],dcnt;
inline void dfs1(int id)
{
son[id]=-1;
siz[id]=1;
for(int j=head[id];j!=-1;j=edge[j].next)
{
if(!dep[edge[j].to])
{
dep[edge[j].to]=dep[id]+1;
fa[edge[j].to]=id;
dfs1(edge[j].to);
siz[id]+=siz[edge[j].to];
if(son[id]==-1||siz[edge[j].to]>siz[son[id]])
{
son[id]=edge[j].to;
}
}
}
}
inline void dfs2(int id,int tp)
{
top[id]=tp;
dcnt++;
dfn[id]=dcnt;
rnk[dcnt]=id;
if(son[id]==-1)
{
return;
}
dfs2(son[id],tp);
for(int j=head[id];j!=-1;j=edge[j].next)
{
if(edge[j].to!=son[id]&&edge[j].to!=fa[id])
{
dfs2(edge[j].to,edge[j].to);
}
}
}
int sum[N],mxn[N],w[N];
inline push_up(int id)
{
sum[id]=sum[id<<1]+sum[id<<1|1];
mxn[id]=max(mxn[id<<1],mxn[id<<1|1]);
}
inline void build(int id,int l,int r)
{
if(l==r)
{
sum[id]=mxn[id]=w[rnk[l]];
return;
}
int mid = l+r>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
push_up(id);
}
inline int query1(int id,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return sum[id];
}
int mid = l+r>>1;
int ans=0;
if(x<=mid)
{
ans+=query1(id<<1,l,mid,x,y);
}
if(y>mid)
{
ans+=query1(id<<1|1,mid+1,r,x,y);
}
return ans;
}
inline int query2(int id,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return mxn[id];
}
int mid = l+r>>1;
int ans=-1e6;
if(x<=mid)
{
ans=max(ans,query2(id<<1,l,mid,x,y));
}
if(y>mid)
{
ans=max(ans,query2(id<<1|1,mid+1,r,x,y));
}
return ans;
}
inline void update(int id,int l,int r,int x,int v)
{
if(l==r)
{
mxn[id]=v;
sum[id]=v;
return;
}
int mid = l+r>>1;
if(x<=mid)
{
update(id<<1,l,mid,x,v);
}
else
{
update(id<<1|1,mid+1,r,x,v);
}
push_up(id);
}
inline int lca(int u,int v)
{
while(top[u]!=top[v])
{
if(dep[top[u]]>dep[top[v]])
{
u = fa[top[u]];
}
else
{
v = fa[top[v]];
}
}
return dep[u]>dep[v]?v:u;
}
inline int querysum(int x,int y)
{
int ret =0,fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]>=dep[fy])
{
ret += query1(1,1,n,dfn[fx],dfn[x]);
x=fa[fx];
}
else
{
ret += query1(1,1,n,dfn[fy],dfn[y]);
y=fa[fy];
}
fx = top[x];
fy = top[y];
}
if(dfn[x]<dfn[y])
{
ret += query1(1,1,n,dfn[x],dfn[y]);
}
else
{
ret += query1(1,1,n,dfn[y],dfn[x]);
}
return ret;
}
inline int querymax(int x,int y)
{
int ret =-1e8,fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]>=dep[fy])
{
ret = max(ret,query2(1,1,n,dfn[fx],dfn[x]));
x=fa[fx];
}
else
{
ret = max(ret,query2(1,1,n,dfn[fy],dfn[y]));
y=fa[fy];
}
fx = top[x];
fy = top[y];
}
if(dfn[x]<dfn[y])
{
ret = max(ret,query2(1,1,n,dfn[x],dfn[y]));
}
else
{
ret = max(ret,query2(1,1,n,dfn[y],dfn[x]));
}
return ret;
}
signed main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
int a,b;
cin>>a>>b;
add_edge(a,b);
add_edge(b,a);
}
for(int i=1;i<=n;i++)
{
cin>>w[i];
}
dep[1]=1;
dfs1(1);
dfs2(1,1);
build(1,1,n);
int q;
for(int i=1;i<=q;i++)
{
cin>>op>>u>>v;
if(!strcmp(op,"CHANGE"))
{
update(1,1,n,dfn[u],v);
}
if(!strcmp(op,"QMAX"))
{
cout<<querymax(u,v);
}
if(!strcmp(op,"QSUM"))
{
cout<<querysum(u,v);
}
}
}