P1505 [国家集训队] 旅游

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;
}
posted @ 2024-01-12 13:58  123wwm  阅读(39)  评论(0)    收藏  举报