#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
#define mid ((l+r)>>1)
#define left_son root<<1,l,mid
#define right_son root<<1|1,mid+1,r
int n,m;
int e,begin[maxn],next[maxn],to[maxn],w[maxn],a[maxn];
struct segment_tree{
int sum,l,r,mark,maxw;
}tree[maxn<<2];
int son[maxn],id[maxn],father[maxn],cnt,deep[maxn],size[maxn],top[maxn],_map[maxn];
inline void add(int x,int y){
to[++e] = y;
next[e] = begin[x];
begin[x] = e;
}
inline void pushup(int root){
tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum;
tree[root].maxw = max(tree[root<<1].maxw,tree[root<<1|1].maxw);
}
inline void build(int root,int l,int r){
tree[root].l = l;
tree[root].r = r;
tree[root].mark = 0;
if(l == r){
tree[root].sum = w[_map[l]];
tree[root].maxw = w[_map[l]];
return;
}
build(left_son);
build(right_son);
pushup(root);
}
inline void update(int root,int l,int r,int num,int k){
if(l == r){
tree[root].sum = k;
tree[root].maxw = k;
return;
}
if(num <= mid)update(left_son,num,k);
else update(right_son,num,k);
pushup(root);
}
inline int query(int root,int l,int r,int al,int ar){
if(al > r || ar < l)return 0;
if(al <= l && ar >= r)return tree[root].sum;
return query(left_son,al,ar)+query(right_son,al,ar);
}
inline int query_max_node(int root,int l,int r,int al,int ar){
if(al > r || ar < l)return -999999999;
if(al <= l && ar >= r)return tree[root].maxw;
return max(query_max_node(left_son,al,ar),query_max_node(right_son,al,ar));
}
inline int query_range(int x,int y){
int ans = 0;
while(top[x] != top[y]){
if(deep[top[x]] < deep[top[y]])swap(x,y);
ans += query(1,1,cnt,id[top[x]],id[x]);
x = father[top[x]];
}
if(deep[x] > deep[y])swap(x,y);
ans += query(1,1,cnt,id[x],id[y]);
return ans;
}
inline int query_max_range(int x,int y){
int ans = -999999999;
while(top[x] != top[y]){
if(deep[top[x]] < deep[top[y]])swap(x,y);
ans = max(ans,query_max_node(1,1,cnt,id[top[x]],id[x]));
x = father[top[x]];
}
if(deep[x] > deep[y])swap(x,y);
ans = max(ans,query_max_node(1,1,cnt,id[x],id[y]));
return ans;
}
inline void dfs1(int x,int fa,int dep){
deep[x] = dep;
father[x] = fa;
size[x] = 1;
int maxson = -999999999;
for(int i = begin[x];i;i = next[i]){
int y = to[i];
if(y == fa)continue;
dfs1(y,x,dep+1);
size[x] += size[y];
if(size[y] > maxson)son[x] = y,maxson = size[y];
}
}
inline void dfs2(int x,int ntop){
id[x] = ++cnt;
top[x] = ntop;
_map[id[x]] = x;
if(!son[x])return;
dfs2(son[x],ntop);
for(int i = begin[x];i;i = next[i]){
int y = to[i];
if(y == father[x] || y == son[x])continue;
dfs2(y,y);
}
}
int main(){
cin>>n;
for(int i = 1,u,v;i < n;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
for(int i = 1;i <= n;i++)scanf("%d",&w[i]);
dfs1(1,0,1);
dfs2(1,1);
build(1,1,n);
cin>>m;
while(m--){
string ask;
int u,v;
cin>>ask>>u>>v;
if(ask == "CHANGE")update(1,1,cnt,id[u],v);
if(ask == "QMAX")printf("%d\n",query_max_range(u,v));
if(ask == "QSUM")printf("%d\n",query_range(u,v));
}
return 0;
}