#include <cstdio>
#include <iostream>
#include <memory.h>
#define lc t << 1
#define rc t << 1 | 1
#define ll long long
#define N 30009
using namespace std;
void to_max(ll& a, ll b)
{
a = (a >= b ? a : b);
}
class SegTree {
private:
struct Seg {
int l, r;
ll sum, mx;
} tr[N << 2];
public:
inline void pushup(int t)
{
Seg* now = &tr[t];
Seg *l_c = &tr[lc], *r_c = &tr[rc];
now->sum = l_c->sum + r_c->sum;
now->mx = max(l_c->mx, r_c->mx);
}
void builder(ll f[], int t, int l, int r)
{
Seg* now = &tr[t];
now->l = l, now->r = r;
if (l == r) {
now->mx = f[l];
now->sum = f[l];
return;
}
int mid = (l + r) >> 1;
builder(f, lc, l, mid);
builder(f, rc, mid + 1, r);
pushup(t);
}
void update(int t, int idx, ll val)
{
Seg* now = &tr[t];
if (now->l == now->r) {
now->mx = val;
now->sum = val;
return;
}
int mid = (now->l + now->r) >> 1;
if (idx <= mid)
update(lc, idx, val);
if (idx > mid)
update(rc, idx, val);
pushup(t);
}
ll rsq(int t, int l, int r)
{
Seg* now = &tr[t];
if (l <= now->l && now->r <= r)
return now->sum;
int mid = (now->l + now->r) >> 1;
ll res = 0;
if (l <= mid)
res += rsq(lc, l, r);
if (r > mid)
res += rsq(rc, l, r);
return res;
}
ll rmq(int t, int l, int r)
{
Seg* now = &tr[t];
if (l <= now->l && now->r <= r)
return now->mx;
int mid = (now->l + now->r) >> 1;
ll res = -1e9;
if (l <= mid)
to_max(res, rmq(lc, l, r));
if (r > mid)
to_max(res, rmq(rc, l, r));
return res;
}
};
SegTree seg_tree;
struct edge {
int to;
int nxt;
} E[N << 1];
int hd[N], tt;
void addedge(int u, int v)
{
E[++tt] = (edge) {v, hd[u]};
hd[u] = tt;
}
ll arr[N], nodeW[N];
int top[N], tI[N], tO[N], son[N];
int p[N], d[N], sz[N];
int n, m;
void init()
{
for (int u = 1; u <= n; ++u)
arr[tI[u]] = nodeW[u];
seg_tree.builder(arr, 1, 1, n);
}
void dfs_sz(int u, int fa)
{
p[u] = fa;
d[u] = d[fa] + 1;
sz[u] = 1;
for (int i = hd[u]; i; i = E[i].nxt) {
int v = E[i].to;
if (v == fa)
continue;
dfs_sz(v, u);
sz[u] += sz[v];
if (sz[v] > sz[son[u]] || sz[v] == sz[son[u]] && v < son[u])
son[u] = v;
}
}
int timer;
void dfs_top(int u, int fa)
{
tI[u] = ++timer;
tO[u] = tI[u] + sz[u] - 1;
top[u] = (u == son[fa] ? top[fa] : u);
if (sz[u] == 1)
return;
dfs_top(son[u], u);
for (int i = hd[u]; i; i = E[i].nxt) {
int v = E[i].to;
if (v == fa || v == son[u])
continue;
dfs_top(v, u);
}
}
void NodeUpd(int u, ll val)
{
seg_tree.update(1, tI[u], val);
}
ll LineRmq(int u, int v)
{
ll res = -1e9;
while (top[u] != top[v]) {
if (d[top[u]] > d[top[u]]) {
to_max(res, seg_tree.rmq(1, tI[top[u]], u));
u = p[top[u]];
} else {
to_max(res, seg_tree.rmq(1, tI[top[v]], v));
v = p[top[v]];
}
}
if (d[u] > d[v])
swap(u, v);
to_max(res, seg_tree.rmq(1, tI[u], tI[v]));
return res;
}
ll LineRsq(int u, int v)
{
ll res = 0;
while (top[u] != top[v]) {
if (d[top[u]] > d[top[v]]) {
res += seg_tree.rsq(1, tI[top[u]], u);
u = p[top[u]];
} else {
res += seg_tree.rsq(1, tI[top[v]], v);
v = p[top[v]];
}
}
if (d[u] > d[v])
swap(u, v);
res += seg_tree.rsq(1, tI[u], tI[v]);
return res;
}
void quick()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main()
{
quick();
cin >> n;
for (int i = 1, u, v; i < n; ++i) {
cin >> u >> v;
addedge(u, v);
addedge(v, u);
}
for (int i = 1; i <= n; ++i)
cin >> nodeW[i];
dfs_sz(1, 0);
dfs_top(1, 0);
init();
cin >> m;
while (m--) {
string op;
int u, v;
ll val;
cin >> op;
if (op == "CHANGE") {
cin >> u >> val;
NodeUpd(u, val);
} else if (op == "QMAX") {
cin >> u >> v;
cout << LineRmq(u, v) << endl;
} else {
cin >> u >> v;
cout << LineRsq(u, v) << endl;
}
}
return 0;
}