#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
struct OriginTree {
int val, dfn, siz, heavySon, fa, dep, top;
} tr[N];
struct SegmentTree {
int lf, rt, sum, mx;
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
} segTree[N<<2];
struct Node {
int ver, pre;
} e[N<<1];
int n, m, root, p, timer, mp[N];
int idx, head[N];
inline void read(int &res) {
res = 0;
bool f = 1;
char ch = getchar();
while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
res = f?res:-res;
}
inline void ade(int u,int v) {
e[++idx].pre = head[u];
e[idx].ver = v;
head[u] = idx;
}
inline void PreDfs(int u,int d) {
tr[u].dep = d;
tr[u].siz = 1;
int curMax = 0xafafafaf;
for (int i = head[u]; i; i = e[i].pre) {
int v = e[i].ver;
if (v == tr[u].fa) continue;
tr[v].fa = u;
PreDfs(v,d+1);
tr[u].siz += tr[v].siz;
if (tr[v].siz > curMax) {
curMax = tr[v].siz;
tr[u].heavySon = v;
}
}
}
inline void TreeDecomposition(int u,int topNode) {
tr[u].dfn = ++timer;
mp[timer] = u;
tr[u].top = topNode;
if (!tr[u].heavySon) return ;
TreeDecomposition(tr[u].heavySon,topNode);
for (int i = head[u]; i; i = e[i].pre) {
int v = e[i].ver;
if (v == tr[u].fa || v == tr[u].heavySon) continue;
TreeDecomposition(v,v);
}
}
inline void SegBuild(int id,int l,int r) {
segTree[id].lf = l, segTree[id].rt = r;
if (segTree[id].lf == segTree[id].rt) {segTree[id].mx = segTree[id].sum = tr[mp[l]].val; return;}
int mid = (l+r)>>1;
SegBuild(lson(id),l,mid);
SegBuild(rson(id),mid+1,r);
segTree[id].sum = segTree[lson(id)].sum + segTree[rson(id)].sum;
segTree[id].mx = max(segTree[lson(id)].mx,segTree[rson(id)].mx);
}
inline void SegSingleModify(int id,int pos,int v) {
if (segTree[id].lf == segTree[id].rt) {
segTree[id].sum = v;
segTree[id].mx = v;
return ;
}
int mid = (segTree[id].lf+segTree[id].rt)>>1;
if (pos <= mid) SegSingleModify(lson(id),pos,v);
else SegSingleModify(rson(id),pos,v);
segTree[id].sum = segTree[lson(id)].sum+segTree[rson(id)].sum;
segTree[id].mx = max(segTree[lson(id)].mx,segTree[rson(id)].mx);
}
inline int SegSectorQueryMax(int id,int l,int r) {
if (l <= segTree[id].lf && r >= segTree[id].rt) return segTree[id].mx;
int mid = (segTree[id].lf+segTree[id].rt)>>1;
int res = 0xafafafaf;
if (l <= mid) res = max(res,SegSectorQueryMax(lson(id),l,r));
if (r > mid) res = max(res,SegSectorQueryMax(rson(id),l,r));
return res;
}
inline int SegSectorQuerySum(int id,int l,int r) {
if (l <= segTree[id].lf && r >= segTree[id].rt) return segTree[id].sum;
int mid = (segTree[id].lf+segTree[id].rt)>>1;
int res = 0;
if (l <= mid) res += SegSectorQuerySum(lson(id),l,r);
if (r > mid) res += SegSectorQuerySum(rson(id),l,r);
return res;
}
inline int ChainQueryMax(int u,int v) {
int res = 0xafafafaf;
while(tr[u].top != tr[v].top) {
if (tr[tr[u].top].dep < tr[tr[v].top].dep) swap(u,v);
res = max(res,SegSectorQueryMax(1,tr[tr[u].top].dfn,tr[u].dfn));
u = tr[tr[u].top].fa;
}
if (tr[u].dfn > tr[v].dfn) res = max(res,SegSectorQueryMax(1,tr[v].dfn,tr[u].dfn));
else res = max(res,SegSectorQueryMax(1,tr[u].dfn,tr[v].dfn));
return res;
}
inline int ChainQuerySum(int u,int v) {
int res = 0;
while (tr[u].top != tr[v].top) {
if (tr[tr[u].top].dep < tr[tr[v].top].dep) swap(u,v);
res += SegSectorQuerySum(1,tr[tr[u].top].dfn,tr[u].dfn);
u = tr[tr[u].top].fa;
}
if (tr[u].dfn > tr[v].dfn) res += SegSectorQuerySum(1,tr[v].dfn,tr[u].dfn);
else res += SegSectorQuerySum(1,tr[u].dfn,tr[v].dfn);
return res;
}
int main() {
ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
cin >> n;
root = 1;
for (int i = 1; i < n; ++i) {
int u, v;
cin >> u >> v;
ade(u,v), ade(v,u);
}
for (int i = 1; i <= n; ++i) {
cin >> tr[i].val;
}
PreDfs(root,1);
TreeDecomposition(root,root);
SegBuild(1,1,n);
read(m);
while(m--) {
string opt;
cin >> opt;
int a, b;
cin >> a >> b;
if (opt[0] == 'C') {
SegSingleModify(root,tr[a].dfn,b);
} else if (opt[1] == 'M') {
cout << ChainQueryMax(a,b) << "\n";
} else {
cout << ChainQuerySum(a,b) << "\n";
}
}
return 0;
}