#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100000 + 5;
int n , q , w[N] , fa[N] , size[N] , dep[N] , son[N] , top[N] , dfn[N] , s[N] , t;
int u , v;
string opt;
vector < int > g[N];
struct Node
{
int l , r , s , mx;
} tree[N * 4 + 5];
void build(int p , int l , int r)
{
int lc = p << 1 , rc = p << 1 | 1;
tree[p].l = l , tree[p].r = r;
if(l == r)
{
tree[p].s = tree[p].mx = w[dfn[l]];
return ;
}
int mid = (l + r) >> 1;
build(lc , l , mid);
build(rc , mid + 1 , r);
tree[p].s = tree[lc].s + tree[rc].s;
tree[p].mx = max(tree[lc].mx , tree[rc].mx);
}
void adde(int p , int x , int y)
{
int lc = p << 1 , rc = p << 1 | 1;
if(tree[p].l == tree[p].r && tree[p].l == x)
{
tree[p].mx = y;
tree[p].s = y;
return ;
}
int mid = (tree[p].l + tree[p].r) >> 1;
if(x <= mid) adde(lc , x , y);
else adde(rc , x , y);
tree[p].s = tree[lc].s + tree[rc].s;
tree[p].mx = max(tree[lc].mx , tree[rc].mx);
}
int query_s(int p , int l , int r)
{
int lc = p << 1 , rc = p << 1 | 1;
if(tree[p].l >= l && tree[p].r <= r) return tree[p].s;
int mid = (tree[p].l + tree[p].r) >> 1;
int res = 0;
if(l <= mid) res += query_s(lc , l , r );
if(r > mid) res += query_s(rc , l , r);
return res;
}
int query_mx(int p , int l , int r)
{
int lc = p << 1 , rc = p << 1 | 1;
if(tree[p].l >= l && tree[p].r <= r) return tree[p].mx;
int mid = (tree[p].l + tree[p].r) >> 1;
int res = -2147483647 ;
if(l <= mid) res = max(res , query_mx(lc , l , r));
if(r > mid) res = max(res , query_mx(rc , l , r));
return res;
}
void dfs(int u)
{
size[u] = 1;
dep[u] = dep[fa[u]] + 1;
for(int i = 0 ; i < g[u].size() ; ++ i )
{
int v = g[u][i];
if(v == fa[u]) continue;
fa[v] = u;
dfs(v);
size[u] += size[v];
if(size[v] > size[son[u]]) son[u] = v;
}
}
void dfs_top(int u , int tp)
{
s[u] = ++t;
dfn[t] = u;
top[u] = tp;
if(son[u]) dfs_top(son[u] , tp);
for(int i = 0 ; i < g[u].size() ; ++ i )
{
int v = g[u][i];
if(v == fa[u] || v == son[u]) continue;
dfs_top(v , v);
}
}
int Max(int u , int v)
{
int fa_u = top[u] , fa_v = top[v];
int ret = -2147483647;
while(fa_u != fa_v)
{
if(dep[fa_u] < dep[fa_v]) swap(u , v) , swap(fa_u , fa_v);
ret = max(ret , query_mx(1 , dfn[fa_u] , dfn[u]));
u = fa[fa_u];
fa_u = top[u];
}
if(dep[u] > dep[v]) swap(u , v);
ret = max(ret , query_mx(1 , dfn[u] , dfn[v]));
return ret;
}
int Sum(int u , int v)
{
int fa_u = top[u] , fa_v = top[v];
int ret = 0;
while(fa_u != fa_v)
{
if(dep[fa_u] < dep[fa_v]) swap(u , v) , swap(fa_u , fa_v);
ret += query_s(1 , dfn[fa_u] , dfn[u]);
u = fa[fa_u];
fa_u = top[u];
}
if(dep[u] > dep[v]) swap(u , v);
ret += query_s(1 , dfn[u] , dfn[v]);
return ret;
}
signed main()
{
cin >> n;
for(int i = 1 ; i < n ; ++ i )
{
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
for(int i = 1 ; i <= n ; ++ i ) cin >> w[i];
cin >> q;
dfs(1);
dfs_top(1 , 1);
build(1 , 1 , t);
while(q--)
{
cin >> opt >> u >> v;
if(opt == "CHANGE")
{
adde(1 , dfn[u] , v);
}
else if(opt == "QMAX")
{
cout << Max(u , v) << endl;
}
else
{
cout << Sum(u , v) << endl;
}
}
return 0;
}
//熟练泼粪 = 树链剖分
wa,只A了三个点