rt
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 200005;
struct tNode {
int fa, dep, hson, top, siz, dfn;
ll val;
}a[N];
int rk[N], edgeid[N];
vector<pair<pair<int, ll>, int> > edge[N];
int n, m;
void Dfs1(int x, int fa) {
a[x].fa = fa, a[x].dep = a[fa].dep + 1, a[x].siz = 1;
for(auto v : edge[x]) {
auto info = v.first;
int id = v.second;
if(info.first == fa) {
edgeid[id] = x;
a[x].val = info.second;
// cout << x << ' ' << fa << endl;
continue;
}
Dfs1(info.first, x);
a[x].siz += a[info.first].siz;
if(a[a[x].hson].siz > a[info.first].siz) {
a[x].hson = info.first;
}
}
}
int cntdfn = 0;
void Dfs2(int x, int top) {
int fa = a[x].fa;
a[x].top = top, a[x].dfn = ++cntdfn;
rk[cntdfn] = x;
if(a[x].hson) {
Dfs2(a[x].hson, top);
}
for(auto v : edge[x]) {
auto info = v.first;
int id = v.second;
if(info.first == fa || info.first == a[x].hson) {
continue;
}
Dfs2(info.first, info.first);
}
}
struct SegTree {
struct tNode {
int l, r, neg;
ll sum, maxv, minv;
}tree[N << 2];
void PushUp(int x) {
tree[x].sum = tree[x << 1].sum + tree[x << 1 | 1].sum;
tree[x].maxv = max(tree[x << 1].maxv, tree[x << 1 | 1].maxv);
tree[x].minv = min(tree[x << 1].minv, tree[x << 1 | 1].maxv);
}
void Build(int x, int l, int r) {
tree[x].l = l, tree[x].r = r;
if(l == r) {
tree[x].sum = tree[x].maxv = tree[x].minv = a[rk[l]].val;
return ;
}
int mid = (l + r) >> 1;
Build(x << 1, l, mid);
Build(x << 1 | 1, mid + 1, r);
PushUp(x);
}
void PushDown(int x) {
if(tree[x].neg) {
tree[x << 1].neg ^= 1, tree[x << 1 | 1].neg ^= 1;
tree[x << 1].sum = -tree[x << 1].sum, tree[x << 1 | 1].sum = -tree[x << 1 | 1].sum;
swap(tree[x << 1].maxv, tree[x << 1].minv), swap(tree[x << 1 | 1].maxv, tree[x << 1 | 1].minv);
tree[x << 1].maxv = -tree[x << 1].maxv, tree[x << 1 | 1].maxv = -tree[x << 1 | 1].maxv;
tree[x << 1].minv = -tree[x << 1].minv, tree[x << 1 | 1].minv = -tree[x << 1 | 1].minv;
tree[x].neg = 0;
}
}
void Modify_sig(int x, int mp, ll v) {
int l = tree[x].l, r = tree[x].r;
if(l == r) {
tree[x].sum = tree[x].maxv = tree[x].minv = v;
return ;
}
int mid = (l + r) >> 1;
PushDown(x);
if(mp <= mid) {
Modify_sig(x << 1, mp, v);
}
else {
Modify_sig(x << 1 | 1, mp, v);
}
PushUp(x);
}
void Modify_neg(int x, int ml, int mr) {
int l = tree[x].l, r = tree[x].r;
// cout << x << ' ' << ml << ' ' << mr << ' ' << l << ' ' << r << endl;
if(ml <= l && r <= mr) {
// cout << "Modified " << x << endl;
tree[x].sum = -tree[x].sum, swap(tree[x].maxv, tree[x].minv);
tree[x].maxv = -tree[x].maxv, tree[x].minv = -tree[x].minv;
tree[x].neg ^= 1;
return ;
}
int mid = (l + r) >> 1;
PushDown(x);
if(ml <= mid) {
Modify_neg(x << 1, ml, mr);
}
if(mr > mid) {
Modify_neg(x << 1 | 1, ml, mr);
}
PushUp(x);
}
ll Query_sum(int x, int ql, int qr) {
int l = tree[x].l, r = tree[x].r;
if(ql <= l && r <= qr) {
return tree[x].sum;
}
int mid = (l + r) >> 1;
PushDown(x);
ll res = 0;
if(ql <= mid) {
res += Query_sum(x << 1, ql, qr);
}
if(qr > mid) {
res += Query_sum(x << 1 | 1, ql, qr);
}
return res;
}
ll Query_maxv(int x, int ql, int qr) {
int l = tree[x].l, r = tree[x].r;
if(ql <= l && r <= qr) {
return tree[x].maxv;
}
int mid = (l + r) >> 1;
PushDown(x);
ll res = LONG_LONG_MIN;
if(ql <= mid) {
res = max(res, Query_maxv(x << 1, ql, qr));
}
if(qr > mid) {
res = max(res, Query_maxv(x << 1 | 1, ql, qr));
}
return res;
}
ll Query_minv(int x, int ql, int qr) {
int l = tree[x].l, r = tree[x].r;
if(ql <= l && r <= qr) {
return tree[x].sum;
}
int mid = (l + r) >> 1;
PushDown(x);
ll res = LONG_LONG_MAX;
if(ql <= mid) {
res = min(res, Query_minv(x << 1, ql, qr));
}
if(qr > mid) {
res = min(res, Query_minv(x << 1 | 1, ql, qr));
}
return res;
}
void Out() {
int i = 1;
while(tree[i].l) {
printf("tree[%d] [%d, %d] : sum = %lld, maxv = %lld, minv = %lld, neg = %lld\n", i, tree[i].l, tree[i].r, tree[i].sum, tree[i].maxv, tree[i].minv, tree[i].neg);
i++;
}
}
}segtree;
void Modify_Edge(int x, ll v) {
segtree.Modify_sig(1, a[edgeid[x]].dfn, v);
}
void Modify_Path(int u, int v) {
while(a[u].top != a[v].top) {
if(a[a[u].top].dep < a[a[v].top].dep) {
swap(u, v);
}
segtree.Modify_neg(1, a[a[u].top].dfn, a[u].dfn);
u = a[a[u].top].fa;
}
segtree.Modify_neg(1, min(a[u].dfn, a[v].dfn) + 1, max(a[u].dfn, a[v].dfn));
}
ll Query_Path_sum(int u, int v) {
ll res = 0;
while(a[u].top != a[v].top) {
if(a[a[u].top].dep < a[a[v].top].dep) {
swap(u, v);
}
res += segtree.Query_sum(1, a[a[u].top].dfn, a[u].dfn);
u = a[a[u].top].fa;
}
res += segtree.Query_sum(1, min(a[u].dfn, a[v].dfn) + 1, max(a[u].dfn, a[v].dfn));
return res;
}
ll Query_Path_maxv(int u, int v) {
ll res = LONG_LONG_MIN;
while(a[u].top != a[v].top) {
if(a[a[u].top].dep < a[a[v].top].dep) {
swap(u, v);
}
res = max(segtree.Query_maxv(1, a[a[u].top].dfn, a[u].dfn), res);
u = a[a[u].top].fa;
}
res = max(segtree.Query_maxv(1, min(a[u].dfn, a[v].dfn) + 1, max(a[u].dfn, a[v].dfn)), res);
return res;
}
ll Query_Path_minv(int u, int v) {
ll res = LONG_LONG_MAX;
while(a[u].top != a[v].top) {
if(a[a[u].top].dep < a[a[v].top].dep) {
swap(u, v);
}
res = min(segtree.Query_minv(1, a[a[u].top].dfn, a[u].dfn), res);
u = a[a[u].top].fa;
}
res = min(segtree.Query_minv(1, min(a[u].dfn, a[v].dfn) + 1, max(a[u].dfn, a[v].dfn)), res);
return res;
}
int main() {
// freopen("P1505_12.in", "r", stdin);
int i;
scanf("%d", &n);
for(i = 1; i < n; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
u++, v++;
edge[u].push_back(make_pair(make_pair(v, w), i));
edge[v].push_back(make_pair(make_pair(u, w), i));
}
Dfs1(1, 0);
// cout << "QwQ" << endl;
Dfs2(1, 1);
segtree.Build(1, 1, n);
segtree.Out();
scanf("%d", &m);
while(m--) {
string op;
cin >> op;
if(op == "C") {
int x;
ll v;
scanf("%d%lld", &x, &v);
Modify_Edge(x, v);
}
else {
int u, v;
scanf("%d%d", &u, &v);
u++, v++;
if(op == "N") {
Modify_Path(u, v);
}
else if(op == "SUM") {
printf("%lld\n", Query_Path_sum(u, v));
}
else if(op == "MAX") {
printf("%lld\n", Query_Path_maxv(u, v));
}
else {
printf("%lld\n", Query_Path_minv(u, v));
}
}
// cout << ("Finished " + op) << endl;
// segtree.Out();
}
}