题意大概是一棵树,有点权,五种操作为链加、链求和、链求 max、链求 min、链 reverse
保证第一和第五操作是直上直下的
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 50005;
namespace fhq {
unsigned pos[MAXN]; int val[MAXN], siz[MAXN], ls[MAXN], rs[MAXN];
bool rev[MAXN]; int add[MAXN]; long long sum[MAXN]; int minv[MAXN], maxv[MAXN];
void addrev(int rt) {rev[rt] ^= 1; swap(ls[rt], rs[rt]);}
void addtag(int rt, int w) {add[rt] += w; val[rt] += w; sum[rt] += 1ll * siz[rt] * w;}
void pushdown(int rt) {
if (rt == 0) return;
if (rev[rt]) addrev(ls[rt]), addrev(rs[rt]), rev[rt] = 0;
if (add[rt]) {
if (ls[rt]) addtag(ls[rt], add[rt]); if (rs[rt]) addtag(rs[rt], add[rt]); add[rt] = 0;
}
}
void pushup(int rt) {
if (rt == 0) return;
siz[rt] = siz[ls[rt]] + siz[rs[rt]] + 1; sum[rt] = sum[ls[rt]] + sum[rs[rt]] + val[rt];
minv[rt] = min({minv[ls[rt]], minv[rs[rt]], val[rt]});
maxv[rt] = max({maxv[ls[rt]], maxv[rs[rt]], val[rt]});
}
void split(int rt, int &x, int &y, int sz) {
if (rt == 0) return x = y = 0, void(); pushdown(rt);
if (siz[ls[rt]] >= sz) split(ls[rt], x, ls[y = rt], sz);
else split(rs[rt], rs[x = rt], y, sz - siz[ls[rt]] - 1);
pushup(x), pushup(y);
}
int merge(int x, int y) {
if ((x && y) == 0) return x | y; pushdown(x); pushdown(y);
if (pos[x] < pos[y]) return rs[x] = merge(rs[x], y), pushup(x), x;
else return ls[y] = merge(x, ls[y]), pushup(y), y;
}
}
vector<int> G[MAXN]; int dep[MAXN], fa[MAXN], maxs[MAXN], siz[MAXN], tp[MAXN];
void dfs1(int u, int f) {
fa[u] = f; siz[u] = 1; dep[u] = dep[f] + 1; for (int v : G[u]) {
if (v == f) continue; dfs1(v, u); siz[u] += siz[v];
maxs[u] = maxs[u] && siz[maxs[u]] > siz[v] ? maxs[u] : v;
}
}
int rt[MAXN], tmprt[MAXN];
void dfs2(int u, int t) {
tp[u] = t; rt[t] = fhq::merge(rt[t], u); if (maxs[u]) dfs2(maxs[u], t);
for (int v : G[u]) if (v != fa[u] && v != maxs[u]) dfs2(v, v);
}
void modify(int u, int v, int w) {
while (tp[u] != tp[v]) {
if (dep[tp[u]] < dep[tp[v]]) swap(u, v);
int tmp; fhq::split(rt[tp[u]], rt[tp[u]], tmp, dep[u] - dep[tp[u]] + 1);
fhq::addtag(rt[tp[u]], w); rt[tp[u]] = fhq::merge(rt[tp[u]], tmp); u = fa[tp[u]];
}
if (dep[u] < dep[v]) swap(u, v);
int tmp; fhq::split(rt[tp[u]], tmp, rt[tp[u]], dep[v] - dep[tp[v]]);
int tmp2; fhq::split(rt[tp[u]], rt[tp[u]], tmp2, dep[u] - dep[v] + 1);
fhq::addtag(rt[tp[u]], w); rt[tp[u]] = fhq::merge(tmp, fhq::merge(rt[tp[u]], tmp2));
}
long long querysum(int u, int v) {
long long ans = 0; while (tp[u] != tp[v]) {
if (dep[tp[u]] < dep[tp[v]]) swap(u, v);
int tmp; fhq::split(rt[tp[u]], rt[tp[u]], tmp, dep[u] - dep[tp[u]] + 1);
ans += fhq::sum[rt[tp[u]]]; rt[tp[u]] = fhq::merge(rt[tp[u]], tmp); u = fa[tp[u]];
}
if (dep[u] < dep[v]) swap(u, v);
int tmp; fhq::split(rt[tp[u]], tmp, rt[tp[u]], dep[v] - dep[tp[v]]);
int tmp2; fhq::split(rt[tp[u]], rt[tp[u]], tmp2, dep[u] - dep[v] + 1);
ans += fhq::sum[rt[tp[u]]]; rt[tp[u]] = fhq::merge(tmp, fhq::merge(rt[tp[u]], tmp2));
return ans;
}
int querymax(int u, int v) {
int ans = 0; while (tp[u] != tp[v]) {
if (dep[tp[u]] < dep[tp[v]]) swap(u, v);
int tmp; fhq::split(rt[tp[u]], rt[tp[u]], tmp, dep[u] - dep[tp[u]] + 1);
ans = max(ans, fhq::maxv[rt[tp[u]]]); rt[tp[u]] = fhq::merge(rt[tp[u]], tmp); u = fa[tp[u]];
}
if (dep[u] < dep[v]) swap(u, v);
int tmp; fhq::split(rt[tp[u]], tmp, rt[tp[u]], dep[v] - dep[tp[v]]);
int tmp2; fhq::split(rt[tp[u]], rt[tp[u]], tmp2, dep[u] - dep[v] + 1);
ans = max(ans, fhq::maxv[rt[tp[u]]]); rt[tp[u]] = fhq::merge(tmp, fhq::merge(rt[tp[u]], tmp2));
return ans;
}
int querymin(int u, int v) {
int ans = 0x7fffffff; while (tp[u] != tp[v]) {
if (dep[tp[u]] < dep[tp[v]]) swap(u, v);
int tmp; fhq::split(rt[tp[u]], rt[tp[u]], tmp, dep[u] - dep[tp[u]] + 1);
ans = min(ans, fhq::minv[rt[tp[u]]]); rt[tp[u]] = fhq::merge(rt[tp[u]], tmp); u = fa[tp[u]];
}
if (dep[u] < dep[v]) swap(u, v);
int tmp; fhq::split(rt[tp[u]], tmp, rt[tp[u]], dep[v] - dep[tp[v]]);
int tmp2; fhq::split(rt[tp[u]], rt[tp[u]], tmp2, dep[u] - dep[v] + 1);
ans = min(ans, fhq::minv[rt[tp[u]]]); rt[tp[u]] = fhq::merge(tmp, fhq::merge(rt[tp[u]], tmp2));
return ans;
}
void reverse(int u, int v) {
if (dep[u] < dep[v]) swap(u, v); int uu = u;
int R = 0; while (tp[u] != tp[v]) {
int tmp; fhq::split(rt[tp[u]], tmp, tmprt[tp[u]], dep[u] - dep[tp[u]] + 1);
R = fhq::merge(tmp, R); u = fa[tp[u]];
}
int tmp; fhq::split(rt[tp[u]], rt[tp[u]], tmp, dep[v] - dep[tp[v]]);
fhq::split(tmp, tmp, tmprt[tp[u]], dep[u] - dep[v] + 1); R = fhq::merge(tmp, R);
fhq::addrev(R); u = uu; while (tp[u] != tp[v]) {
int tmp; fhq::split(R, R, tmp, fhq::siz[R] - (dep[u] - dep[tp[u]] + 1));
rt[tp[u]] = fhq::merge(tmp, tmprt[tp[u]]); u = fa[tp[u]];
}
rt[tp[u]] = fhq::merge(rt[tp[u]], fhq::merge(R, tmprt[tp[u]]));
}
mt19937 rnd(time(0));
int main() {
fhq::minv[0] = 0x7fffffff; for (int i = 1; i < MAXN; i++) fhq::siz[i] = 1;
int n, m, r; scanf("%d %d %d", &n, &m, &r);
for (int i = 1; i <= n; i++) fhq::pos[i] = rnd();
for (int i = 1; i < n; i++) {
int u, v; scanf("%d %d", &u, &v); G[u].push_back(v); G[v].push_back(u);
} dfs1(r, r); dfs2(r, r); while (m--) {
char str[20]; int a, b, c; scanf("%s %d %d", str, &a, &b);
if (str[2] == 'c') scanf("%d", &c), modify(a, b, c);
if (str[0] == 'S') printf("%lld\n", querysum(a, b));
if (str[1] == 'a') printf("%d\n", querymax(a, b));
if (str[1] == 'i') printf("%d\n", querymin(a, b));
if (str[2] == 'v') reverse(a, b);
}
}