调了 2h 了。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
typedef tuple <int, int, int> t3i;
#define MT make_tuple
const int N = 1e6 + 10;
int n, m;
struct Edge { int u, v, w; } e[N];
vector <pii> G[N];
int siz[N], fa[N], a[N], son[N], dfn[N], top[N], dep[N];
namespace Seg {
int tag[N << 2], sum[N << 2], mav[N << 2], miv[N << 2];
#define ls p << 1
#define rs p << 1 | 1
#define mid ((l + r) >> 1)
void upd (int p) {
sum[p] = sum[ls] + sum[rs];
mav[p] = max (mav[ls], mav[rs]);
miv[p] = min (miv[ls], miv[rs]);
}
void build (int p, int l, int r) {
if (l == r) return sum[p] = mav[p] = miv[p] = a[l], void (0);
build (ls, l, mid); build (rs, mid + 1, r);
upd (p);
}
void Set (int p) {
sum[p] *= -1; int x = miv[p], y = mav[p];
mav[p] = -x, miv[p] = -y; tag[p] ^= 1;
}
void push_down (int p) {
if (tag[p]) Set (ls), Set (rs), tag[p] = 0;
}
void modify1 (int p, int l, int r, int pos, int val) {
if (l == r) return sum[p] = mav[p] = miv[p] = val, void (0);
push_down (p);
if (pos <= mid) modify1 (ls, l, mid, pos, val);
else modify1 (rs, mid + 1, r, pos, val);
upd (p);
}
void modify2 (int p, int l, int r, int L, int R) {
if (L <= l && r <= R) return Set (p), void (0);
push_down (p);
if (L <= mid) modify2 (ls, l, mid, L, R);
if (R > mid) modify2 (rs, mid + 1, r, L, R);
upd (p);
}
t3i merge (t3i x, t3i y) {
return {get <0> (x) + get <0> (y),
max (get <1> (x), get <1> (y)),
min (get <2> (x), get <2> (y)) };
}
t3i query (int p, int l, int r, int L, int R) {
if (L <= l && r <= R) return {sum[p], mav[p], miv[p]};
t3i S = {0, -1001, 1001};
push_down (p);
if (L <= mid) S = merge (S, query (ls, l, mid, L, R));
if (R > mid) S = merge (S, query (rs, mid + 1, r, L, R));
return S;
}
}
void dfs1 (int u, int FA) {
siz[u] = 1; fa[u] = FA; dep[u] = dep[FA] + 1;
for (auto [v, w] : G[u]) {
if (v == FA) continue;
a[v] = w; dfs1 (v, u);
siz[u] += siz[v];
if (siz[v] > siz[son[u]]) son[u] = v;
}
}
int tot = 0;
void dfs2 (int u, int tp) {
top[u] = tp; dfn[u] = ++tot;
if (son[u]) dfs2 (son[u], tp);
for (auto [v, w] : G[u])
if (v != fa[u] && v != son[u]) dfs2 (v, v);
}
void Opt1 (int id, int val) {
int u = e[id].u, v = e[id].v;
if (v == fa[u]) swap (u, v);
Seg::modify1 (1, 1, n, dfn[v], val);
}
void Opt2 (int u, int v) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap (u, v);
Seg::modify2 (1, 1, n, dfn[top[u]], dfn[u]);
u = fa[top[u]];
}
if (dep[u] > dep[v]) swap (u, v);
Seg::modify2 (1, 1, n, dfn[u] + 1, dfn[v]);
}
t3i ask (int u, int v) {
t3i res = {0, -1001, 1001};
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap (u, v);
res = Seg::merge (res, Seg::query (1, 1, n, dfn[top[u]], dfn[u]));
u = fa[top[u]];
}
if (dep[u] > dep[v]) swap (u, v);
res = Seg::merge (res, Seg::query (1, 1, n, dfn[u] + 1, dfn[v]));
return res;
}
signed main () {
#ifdef ZJY
freopen ("in.cpp", "r", stdin);
freopen ("out.cpp", "w", stdout);
#endif
ios::sync_with_stdio (false);
cin.tie (0); cout.tie (0);
cin >> n;
for (int i = 1, u, v, w; i < n; i++) {
cin >> u >> v >> w; u++, v++;
G[u].push_back ({v, w});
G[v].push_back ({u, w});
e[i] = {u, v, w};
}
dfs1 (1, 0); dfs2 (1, 1);
Seg::build (1, 1, n);
cin >> m;
string opt; int u, v;
while (m--) {
cin >> opt >> u >> v; u++, v++;
if (opt == "C") u--, v--, Opt1 (u, v);
else if (opt == "N") Opt2 (u, v);
else if (opt == "SUM") cout << (get <0> (ask (u, v))) << '\n';
else if (opt == "MAX") cout << (get <1> (ask (u, v))) << '\n';
else cout << (get <2> (ask (u, v))) << '\n';
}
return 0;
}