P1505 [国家集训队] 旅游
树链剖分,将边权转化为点权。
单点修改,区间修改,区间查询,树上乱跳。
还要记录第 \(i\) 条树边的边权记录在哪个点上。
有意思的是我不知道取什么变量名好,感谢 houwz351 的意见,让我取名为 。amns
(阿米诺斯)
这是我写过最长的代码了(4.78 kb)。
不过一发就过了/jy/jy。
code:
#include <bits/stdc++.h>
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define pb push_back
#define mk make_pair
#define ll long long
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
inline int read() {
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') f = c == '-' ? -1 : f, c = getchar();
while ('0' <= c && c <= '9') x = (x<<3)+(x<<1)+(c^48), c = getchar();
return x*f;
}
inline void write(int x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x/10);
putchar(x%10+'0');
}
const int N = 2e5+5, M = N<<2, inf = 1e9;
struct edge { int to, next, w, id; } e[N<<1];
int n, m, tot, idx, a[N], d[N], fa[N], id[N], to[N], siz[N], son[N], top[N], amns[N], head[N];
int mn[M], mx[M], sum[M], rev[M];
void add(int x, int y, int w, int id) { e[++tot] = {y, head[x], w, id}, head[x] = tot; }
void dfs1(int x, int f) {
d[x] = d[f]+1, fa[x] = f, siz[x] = 1; int mx = 0;
for (int i = head[x]; i; i = e[i].next) {
int y = e[i].to;
if (y == f) continue;
dfs1(y, x);
a[y] = e[i].w;
siz[x] += siz[y];
amns[e[i].id] = y;
if (siz[y] > mx) son[x] = y, mx = siz[y];
}
}
void dfs2(int x, int topf) {
id[x] = ++idx, to[idx] = x, top[x] = topf;
if (!son[x]) return;
dfs2(son[x], topf);
for (int i = head[x]; i; i = e[i].next) {
int y = e[i].to;
if (y == fa[x] || y == son[x]) continue;
dfs2(y, y);
}
}
void pushup(int p) {
mn[p] = min(mn[ls], mn[rs]);
mx[p] = max(mx[ls], mx[rs]);
sum[p] = sum[ls]+sum[rs];
}
void pushdown(int p) {
if (!rev[p]) return;
swap(mn[ls], mx[ls]), mn[ls] *= -1, mx[ls] *= -1;
swap(mn[rs], mx[rs]), mn[rs] *= -1, mx[rs] *= -1;
sum[ls] *= -1, sum[rs] *= -1;
rev[ls] ^= 1, rev[rs] ^= 1;
rev[p] = 0;
}
void build(int p, int l, int r) {
if (l == r) return (void)(mn[p] = mx[p] = sum[p] = a[to[l]]);
int mid = l+r>>1;
build(ls, l, mid), build(rs, mid+1, r);
pushup(p);
}
void modify(int p, int l, int r, int x, int v) {
if (l == r) return (void)(mn[p] = mx[p] = sum[p] = v);
pushdown(p);
int mid = l+r>>1;
x <= mid ? modify(ls, l, mid, x, v) : modify(rs, mid+1, r, x, v);
pushup(p);
}
void rever(int p, int l, int r, int ql, int qr) {
if (qr < l || r < ql) return;
if (ql <= l && r <= qr) {
swap(mn[p], mx[p]), mn[p] *= -1, mx[p] *= -1;
sum[p] *= -1, rev[p] ^= 1;
return;
}
pushdown(p);
int mid = l+r>>1;
rever(ls, l, mid, ql, qr), rever(rs, mid+1, r, ql, qr);
pushup(p);
}
int qmn(int p, int l, int r, int ql, int qr) {
if (qr < l || r < ql) return inf;
if (ql <= l && r <= qr) return mn[p];
pushdown(p);
int mid = l+r>>1;
return min(qmn(ls, l, mid, ql, qr), qmn(rs, mid+1, r, ql, qr));
}
int qmx(int p, int l, int r, int ql, int qr) {
if (qr < l || r < ql) return -inf;
if (ql <= l && r <= qr) return mx[p];
pushdown(p);
int mid = l+r>>1;
return max(qmx(ls, l, mid, ql, qr), qmx(rs, mid+1, r, ql, qr));
}
int qsum(int p, int l, int r, int ql, int qr) {
if (qr < l || r < ql) return 0;
if (ql <= l && r <= qr) return sum[p];
pushdown(p);
int mid = l+r>>1;
return qsum(ls, l, mid, ql, qr)+qsum(rs, mid+1, r, ql, qr);
}
void opp(int x, int y) {
while (top[x] != top[y]) {
if (d[top[x]] < d[top[y]]) swap(x, y);
rever(1, 1, n, id[top[x]], id[x]);
x = fa[top[x]];
}
if (d[x] > d[y]) swap(x, y);
if (id[x] < id[y]) rever(1, 1, n, id[x]+1, id[y]);
}
int que_mn(int x, int y) {
int ans = inf;
while (top[x] != top[y]) {
if (d[top[x]] < d[top[y]]) swap(x, y);
ans = min(ans, qmn(1, 1, n, id[top[x]], id[x]));
x = fa[top[x]];
}
if (d[x] > d[y]) swap(x, y);
if (id[x] < id[y]) ans = min(ans, qmn(1, 1, n, id[x]+1, id[y]));
return ans;
}
int que_mx(int x, int y) {
int ans = -inf;
while (top[x] != top[y]) {
if (d[top[x]] < d[top[y]]) swap(x, y);
ans = max(ans, qmx(1, 1, n, id[top[x]], id[x]));
x = fa[top[x]];
}
if (d[x] > d[y]) swap(x, y);
if (id[x] < id[y]) ans = max(ans, qmx(1, 1, n, id[x]+1, id[y]));
return ans;
}
int que_sum(int x, int y) {
int ans = 0;
while (top[x] != top[y]) {
if (d[top[x]] < d[top[y]]) swap(x, y);
ans += qsum(1, 1, n, id[top[x]], id[x]);
x = fa[top[x]];
}
if (d[x] > d[y]) swap(x, y);
if (id[x] < id[y]) ans += qsum(1, 1, n, id[x]+1, id[y]);
return ans;
}
int main() {
n = read();
for (int i = 1; i < n; ++i) {
int x = read()+1, y = read()+1, w = read();
add(x, y, w, i), add(y, x, w, i);
}
dfs1(1, 0), dfs2(1, 1), build(1, 1, n);
m = read();
while (m--) {
string op; cin >> op;
int x = read(), y = read();
if (op == "C") modify(1, 1, n, id[amns[x]], y);
else if (op == "N") opp(x+1, y+1);
else if (op == "SUM") write(que_sum(x+1, y+1)), enter;
else if (op == "MAX") write(que_mx(x+1, y+1)), enter;
else write(que_mn(x+1, y+1)), enter;
}
return 0;
}