#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 3e5 + 5;
int n;
int w[MAXN];
vector<int> edge[MAXN];
int L[MAXN],R[MAXN],rdfn[MAXN];
int sz[MAXN],top[MAXN],son[MAXN],fa[MAXN];
int dep[MAXN];
int tim = 0;
void dfs(int u,int fat){
L[u] = ++tim;
rdfn[tim] = u;
sz[u] = 1;
fa[u] = fat;
dep[u] = dep[fat] + 1;
for(int i = 0; i < edge[u].size(); i++){
int v = edge[u][i];
if(v == fat){
continue;
}
dfs(v,u);
sz[u] += sz[v];
if(!son[u] || sz[son[u]] < sz[v]){
son[u] = v;
}
}
R[u] = tim;
}
void dfs2(int u,int fat,int tp){
top[u] = tp;
if(son[u]){
dfs2(son[u],u,tp);
}
for(int i = 0; i < edge[u].size(); i++){
int v = edge[u][i];
if(v == fat || v == son[u]){
continue;
}
dfs2(v,u,v);
}
}
typedef struct TR{
int l,r,sum,mx;
}TR;
TR tr[MAXN << 2];
int ls(int pos){
return pos << 1;
}
int rs(int pos){
return pos << 1 | 1;
}
void push_up(int pos){
tr[pos].sum = tr[ls(pos)].sum + tr[rs(pos)].sum;
tr[pos].mx = max(tr[ls(pos)].mx,tr[rs(pos)].mx);
}
void build(int pos,int l,int r){
tr[pos].l = l;
tr[pos].r = r;
tr[pos].sum = 0;
tr[pos].mx = -1e18;
if(l == r){
tr[pos].sum = w[rdfn[l]];
tr[pos].mx = tr[pos].sum;
return;
}
int mid = (l + r) >> 1;
build(ls(pos),l,mid);
build(rs(pos),mid + 1,r);
push_up(pos);
}
void update(int pos,int p,int k){
int l = tr[pos].l,r = tr[pos].r;
if(l == r){
tr[pos].sum = k;
tr[pos].mx = k;
return;
}
int mid = (l + r) >> 1;
if(p <= mid){
update(ls(pos),p,k);
}
if(p > mid){
update(rs(pos),p,k);
}
push_up(pos);
}
int query_sum(int pos,int L,int R){
int l = tr[pos].l,r = tr[pos].r;
if(l >= L && r <= R){
return tr[pos].sum;
}
int res = 0;
int mid = (l + r) >> 1;
if(L <= mid){
res += query_sum(ls(pos),L,R);
}
if(R > mid){
res += query_sum(rs(pos),L,R);
}
return res;
}
int query_max(int pos,int L,int R){
int l = tr[pos].l,r = tr[pos].r;
if(l >= L && r <= R){
return tr[pos].mx;
}
int res = -1e18;
int mid = (l + r) >> 1;
if(L <= mid){
res = max(res,query_max(ls(pos),L,R));
}
if(R > mid){
res = max(res,query_max(rs(pos),L,R));
}
return res;
}
int query(int u,int v,int id){
if(id == 1){
int res = -1e18;
while(top[u] != top[v]){
if(dep[fa[top[u]]] > dep[fa[top[v]]]){
res = max(res,query_max(1,L[top[u]],L[u]));
u = fa[top[u]];
}
else{
res = max(res,query_max(1,L[top[v]],L[v]));
v = fa[top[v]];
}
}
if(dep[u] > dep[v]){
swap(u,v);
}
res = max(res,query_max(1,L[u],L[v]));
return res;
}
else{
int res = 0;
while(top[u] != top[v]){
if(dep[fa[top[u]]] > dep[fa[top[v]]]){
res += query_sum(1,L[top[u]],L[u]);
u = fa[top[u]];
}
else{
res += query_sum(1,L[top[v]],L[v]);
v = fa[top[v]];
}
}
if(dep[u] > dep[v]){
swap(u,v);
}
res += query_sum(1,L[u],L[v]);
return res;
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for(int i = 1; i < n; i++){
int a,b;
cin >> a >> b;
edge[a].push_back(b);
edge[b].push_back(a);
}
for(int i = 1; i <= n; i++){
cin >> w[i];
}
dfs(1,0);
dfs2(1,0,1);
build(1,1,n);
int q;
cin >> q;
while(q--){
string opt;
cin >> opt;
if(opt == "CHANGE"){
int u,t;
cin >> u >> t;
update(1,L[u],t);
}
else if(opt == "QMAX"){
int u,v;
cin >> u >> v;
cout << query(u,v,1) << endl;
}
else{
int u,v;
cin >> u >> v;
cout << query(u,v,2) << endl;
}
}
}