#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define ll long long
#define ull unsigned long long
#define int ll
int read()
{
ll now = 0, nev = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
nev = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
now = (now << 1) + (now << 3) + (c & 15);
c = getchar();
}
return now * nev;
}
const int MAXN = 1e6 + 10;
const int INF = 1e18;
int n, q;
int a[MAXN];
int head[MAXN], tt = 0;
struct edge
{
int to, nxt, dis;
} e[MAXN << 1];
void add(int x, int y, int z)
{
e[++tt].nxt = head[x];
head[x] = tt;
e[tt].to = y;
e[tt].dis = z;
}
struct node
{
int x, y;
} id[MAXN];
int fa[MAXN], son[MAXN], siz[MAXN], dep[MAXN];
void dfs1(int u, int fat)
{
dep[u] = dep[fat] + 1;
siz[u] = 1;
fa[u] = fat;
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to, w = e[i].dis;
if (v == fat)
continue;
a[v] = w;
dfs1(v, u);
siz[u] += siz[v];
if (siz[son[u]] < siz[v])
son[u] = v;
}
}
int top[MAXN], dfn[MAXN], seg[MAXN], num = 0;
void dfs2(int u, int topfa)
{
top[u] = topfa;
dfn[u] = ++num;
seg[dfn[u]] = a[u];
if (son[u])
{
dfs2(son[u], topfa);
return;
}
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == fa[u] || v == son[u])
continue;
dfs2(v, v);
}
}
struct tree
{
int l, r;
int sum;
int mx, mn;
int tag;
} tr[MAXN << 2];
void pushup(int k)
{
tr[k].sum = tr[k << 1].sum + tr[k << 1 | 1].sum;
tr[k].mx = max(tr[k << 1].mx, tr[k << 1 | 1].mx);
tr[k].mn = min(tr[k << 1].mn, tr[k << 1 | 1].mn);
}
void build(int k, int l, int r)
{
tr[k].l = l, tr[k].r = r;
if (l == r)
{
tr[k].sum = tr[k].mx = tr[k].mn = seg[l];
return;
}
int mid = (l + r) >> 1;
build(k << 1, l, mid), build(k << 1 | 1, mid + 1, r);
pushup(k);
}
void pushdown(int k)
{
if (tr[k].tag)
{
tr[k << 1].sum = -tr[k << 1].sum;
tr[k << 1 | 1].sum = -tr[k << 1 | 1].sum;
int tmp1 = tr[k << 1].mx, tmp2 = tr[k << 1 | 1].mx;
tr[k << 1].mx = -tr[k << 1].mn;
tr[k << 1 | 1].mx = -tr[k << 1 | 1].mn;
tr[k << 1].mn = -tmp1;
tr[k << 1 | 1].mn = -tmp2;
tr[k << 1].tag ^= 1;
tr[k << 1 | 1].tag ^= 1;
tr[k].tag ^= 1;
}
}
void modefy1(int k, int x, int v)
{
if (tr[k].l == tr[k].r)
{
tr[k].sum = tr[k].mx = tr[k].mn = v;
return;
}
pushdown(k);
int mid = (tr[k].l + tr[k].r) >> 1;
if (x <= mid)
modefy1(k << 1, x, v);
else
modefy1(k << 1 | 1, x, v);
pushup(k);
}
void change(int x, int y, int z)
{
if (fa[x] == y)
modefy1(1, dfn[x], z);
else
modefy1(1, dfn[y], z);
}
void modefy2(int k, int l, int r)
{
if (l <= tr[k].l && tr[k].r <= r)
{
int tmp = tr[k].mx;
tr[k].sum = -tr[k].sum, tr[k].mx = -tr[k].mn, tr[k].mn = -tmp;
tr[k].tag ^= 1;
return;
}
pushdown(k);
int mid = (tr[k].l + tr[k].r) >> 1;
if (l <= mid)
modefy2(k << 1, l, r);
if (r > mid)
modefy2(k << 1 | 1, l, r);
pushup(k);
}
int query_sum(int k, int l, int r)
{
if (l <= tr[k].l && tr[k].r <= r)
return tr[k].sum;
pushdown(k);
int res = 0;
int mid = (tr[k].l + tr[k].r) >> 1;
if (l <= mid)
res += query_sum(k << 1, l, r);
if (r > mid)
res += query_sum(k << 1 | 1, l, r);
return res;
}
int query_max(int k, int l, int r)
{
if (l <= tr[k].l && tr[k].r <= r)
return tr[k].mx;
pushdown(k);
int res = -INF;
int mid = (tr[k].l + tr[k].r) >> 1;
if (l <= mid)
res = max(res, query_sum(k << 1, l, r));
if (r > mid)
res = max(res, query_sum(k << 1 | 1, l, r));
return res;
}
int query_min(int k, int l, int r)
{
if (l <= tr[k].l && tr[k].r <= r)
return tr[k].mn;
pushdown(k);
int res = INF;
int mid = (tr[k].l + tr[k].r) >> 1;
if (l <= mid)
res = min(res, query_sum(k << 1, l, r));
if (r > mid)
res = min(res, query_sum(k << 1 | 1, l, r));
return res;
}
void modefy(int x, int y)
{
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]])
swap(x, y);
modefy2(1, dfn[top[x]], dfn[x]);
x = fa[top[x]];
}
if (dep[x] > dep[y])
swap(x, y);
modefy2(1, dfn[x] + 1, dfn[y]);
}
int gsum(int x, int y)
{
int res = 0;
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]])
swap(x, y);
res += query_sum(1, dfn[top[x]], dfn[x]);
x = fa[top[x]];
}
if (dep[x] > dep[y])
swap(x, y);
res += query_sum(1, dfn[x] + 1, dfn[y]);
return res;
}
int gmax(int x, int y)
{
int res = -INF;
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]])
swap(x, y);
res = max(res, query_max(1, dfn[top[x]], dfn[x]));
x = fa[top[x]];
}
if (dep[x] > dep[y])
swap(x, y);
res = max(res, query_max(1, dfn[x] + 1, dfn[y]));
return res;
}
int gmin(int x, int y)
{
int res = INF;
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]])
swap(x, y);
res = min(res, query_min(1, dfn[top[x]], dfn[x]));
x = fa[top[x]];
}
if (dep[x] > dep[y])
swap(x, y);
res = min(res, query_min(1, dfn[x] + 1, dfn[y]));
return res;
}
signed main()
{
n = read();
for (int i = 1; i < n; i++)
{
int x = read(), y = read(), z = read();
x++, y++;
add(x, y, z), add(y, x, z);
id[i].x = x, id[i].y = y;
}
dfs1(1, 0), dfs2(1, 0);
build(1, 1, n);
q = read();
while (q--)
{
string op;
cin >> op;
int x = read(), y = read();
x++, y++;
if (op == "C")
{
x--, y--;
change(id[x].x, id[x].y, y);
}
if (op == "N")
modefy(x, y);
if (op == "SUM")
printf("%lld\n", gsum(x, y));
if (op == "MAX")
printf("%lld\n", gmax(x, y));
if (op == "MIN")
printf("%lld\n", gmin(x, y));
}
return 0;
}