#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1000005;
const int cs = 2147483647;
int n, m, head[N], a[N], tot, cnt;
string op;
struct Node{
int to, net, ed;
}e[N];
struct T{
int add, sum, maxx, minn;
T() {add = sum = 0, maxx = -cs, minn = cs;}
}Tree[N];
struct jc{
int fa, d, size, hson, seg, rev, top;
}E[N];
struct kun{
int x, y;
}id[N];
void add(int x, int y, int z) {
e[++tot].to = y;
e[tot].ed = z;
e[tot].net = head[x];
head[x] = tot;
}
void dfs1(int x, int F) {
E[x].size = 1, E[x].fa = F, E[x].d = E[F].d + 1;
for (int i = head[x]; i; i = e[i].net) {
int y = e[i].to, z = e[i].ed;
if (y == F) continue;
dfs1(y, x);
a[y] = z;
E[x].size += E[y].size;
if (E[y].size > E[E[x].hson].size) E[x].hson = y;
}
}
void dfs2(int x, int Top) {
E[x].top = Top, E[x].seg = ++cnt, E[cnt].rev = a[x];
if (E[x].hson) dfs2(E[x].hson, Top);
for (int i = head[x]; i; i = e[i].net) {
int y = e[i].to;
if (!E[y].top) dfs2(y, y);
}
}
void Push_up(int p) {
Tree[p].sum = Tree[p * 2].sum + Tree[p * 2 + 1].sum;
Tree[p].maxx = max(Tree[p * 2].maxx, Tree[p * 2 + 1].maxx);
Tree[p].minn = min(Tree[p * 2].minn, Tree[p * 2 + 1].minn);
}
void Build(int p, int l, int r) {
if (l == r) {
Tree[p].sum = Tree[p].maxx = Tree[p].minn = E[l].rev;
return ;
}
int mid = (l + r) / 2;
Build(p * 2, l, mid);
Build(p * 2 + 1, mid + 1, r);
Push_up(p);
}
void Push_down(int p) {
if(!Tree[p].add) return;
Tree[p * 2].add ^= 1;
Tree[p * 2 + 1].add ^= 1;
Tree[p * 2].maxx = -Tree[p * 2].maxx, Tree[p * 2 + 1].maxx = -Tree[p * 2 + 1].maxx;
Tree[p * 2].minn = -Tree[p * 2].minn, Tree[p * 2 + 1].minn = -Tree[p * 2 + 1].minn;
Tree[p * 2].sum = -Tree[p * 2].sum, Tree[p * 2 + 1].sum = -Tree[p * 2 + 1].sum;
swap(Tree[p * 2].maxx, Tree[p * 2].minn);
swap(Tree[p * 2 + 1].maxx, Tree[p * 2 + 1].minn);
Tree[p].add = 0;
}
void Change(int p, int l, int r, int x, int k) {
if (l == r) {
Tree[p].sum = Tree[p].maxx = Tree[p].minn = k;
return ;
}
int mid = (l + r) / 2;
Push_down(p);
if (x <= mid) Change(p * 2, l, mid, x, k);
if (x > mid) Change(p * 2 + 1, mid + 1, r, x, k);
Push_up(p);
}
void fChange(int p, int l, int r, int L, int R) {
if (l >= L && r <= R) {
Tree[p].add ^= 1;
Tree[p].sum = -Tree[p].sum;
Tree[p].maxx = -Tree[p].maxx;
Tree[p].minn = -Tree[p].minn;
swap(Tree[p].maxx, Tree[p].minn);
return ;
}
int mid = (l + r) / 2;
Push_down(p);
if (L <= mid) fChange(p * 2, l, mid, L, R);
if (R > mid) fChange(p * 2 + 1, mid + 1, r, L, R);
Push_up(p);
}
int Query_sum(int p, int l, int r, int L, int R) {
if (l >= L && r <= R) return Tree[p].sum;
int mid = (l + r) / 2, ans = 0;
Push_down(p);
if (L <= mid) ans += Query_sum(p * 2, l, mid, L, R);
if (R > mid) ans += Query_sum(p * 2 + 1, mid + 1, r, L, R);
return ans;
}
int Query_max(int p, int l, int r, int L, int R) {
int maxn = -cs;
if (l >= L && r <= R) return Tree[p].maxx;
int mid = (l + r) / 2;
Push_down(p);
if (L <= mid) maxn = max(maxn, Query_max(p * 2, l, mid, L, R));
if (R > mid) maxn = max(maxn, Query_max(p * 2 + 1, mid + 1, r, L, R));
return maxn;
}
int Query_min(int p, int l, int r, int L, int R) {
int mini = cs;
if (l >= L && r <= R) return Tree[p].minn;
int mid = (l + r) / 2;
Push_down(p);
if (L <= mid) mini = min(mini, Query_min(p * 2, l, mid, L, R));
if (R > mid) mini = min(mini, Query_min(p * 2 + 1, mid + 1, r, L, R));
return mini;
}
void iChange(int x, int y) {
int topx = E[x].top, topy = E[y].top;
while (topx != topy) {
if (E[topx].d < E[topy].d) {
swap(x, y);
swap(topx, topy);
}
fChange(1, 1, cnt, E[topx].seg, E[x].seg);
x = E[topx].fa;
topx = E[x].top;
}
if (E[x].d > E[y].d) swap(x, y);
fChange(1, 1, cnt, E[x].seg + 1, E[y].seg);
}
int iQuery_sum(int x, int y) {
int topx = E[x].top, topy = E[y].top, ans = 0;
while (topx != topy) {
if (E[topx].d < E[topy].d) {
swap(x, y);
swap(topx, topy);
}
ans += Query_sum(1, 1, cnt, E[topx].seg, E[x].seg);
x = E[topx].fa;
topx = E[x].top;
}
if (E[x].d > E[y].d) swap(x, y);
ans += Query_sum(1, 1, cnt, E[x].seg + 1, E[y].seg);
return ans;
}
int iQuery_max(int x, int y) {
int topx = E[x].top, topy = E[y].top, ansmax = -cs;
while (topx != topy) {
if (E[topx].d < E[topy].d) {
swap(x, y);
swap(topx, topy);
}
ansmax = max(ansmax, Query_max(1, 1, cnt, E[topx].seg, E[x].seg));
x = E[topx].fa;
topx = E[x].top;
}
if (E[x].d > E[y].d) swap(x, y);
ansmax = max(ansmax, Query_max(1, 1, cnt, E[x].seg + 1, E[y].seg));
return ansmax;
}
int iQuery_min(int x, int y) {
int topx = E[x].top, topy = E[y].top, ansmin = cs;
while (topx != topy) {
if (E[topx].d < E[topy].d) {
swap(x, y);
swap(topx, topy);
}
ansmin = min(ansmin, Query_min(1, 1, cnt, E[topx].seg + 1, E[x].seg));
x = E[topx].fa;
topx = E[x].top;
}
if (E[x].d > E[y].d) swap(x, y);
ansmin = min(ansmin, Query_min(1, 1, cnt, E[x].seg + 1, E[y].seg));
return ansmin;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for (int i = 1, x, y, z; i < n; i++) {
cin >> x >> y >> z;
add(x + 1, y + 1, z);
add(y + 1, x + 1, z);
}
dfs1(1, 0);
dfs2(1, 1);
Build(1, 1, cnt);
cin >> m;
for (int i = 1, x, y; i <= m; i++) {
cin >> op >> x >> y;
if (op[0] == 'C') Change(1, 1, cnt, (x + 1 == E[y + 1].fa ? E[y + 1].seg : E[x + 1].seg), y);
if (op[0] == 'N') fChange(1, 1, cnt, x + 1, y + 1);
if (op[0] == 'S') cout << iQuery_sum(x + 1, y + 1) << '\n';
if (op[0] == 'M' && op[1] == 'A') cout << iQuery_max(x + 1, y + 1) << '\n';
if (op[0] == 'M' && op[1] == 'I') cout << iQuery_min(x + 1, y + 1) << '\n';
}
return 0;
}