树链剖分爆零求助
查看原帖
树链剖分爆零求助
637796
Xy_top楼主2023/6/17 06:22

线段树是按照 扶苏的问题 那题写的,然后错了,感觉树剖部分没错,贴代码:

#include <iostream>
#define maxn 1000000001
using namespace std;
int n, k, cnt;
//基础树上需求
int fa[100005], dep[100005];
//树剖需求 
int sz[100005], top[100005], wson[100005];
//树剖线段树需求
int num[100005], val[100005];
//线段树需求
int ma[400005], tag[400005], cov[400005]; 
//前向星需求 
int pre[100005];
struct Node {int from, to, len, next;}a[200005];
void add (int x, int y, int z) {
	a[++ k] = {x, y, z, pre[x]};
	pre[x] = k;
}
//树剖 dfs 
void dfs1 (int x) {
	for (int i = pre[x]; i; i = a[i].next) {
		int v = a[i].to;
		if (v == fa[x]) continue;
		dep[v] = dep[x] + 1;
		fa[v] = x;
		dfs1 (v);
		if (sz[v] > sz[wson[x] ]) wson[x] = v;
	}
	sz[fa[x] ] += ++ sz[x];
}
void dfs2 (int x, int t) {
	top[x] = t;
	num[x] = ++ cnt;
	if (wson[x]) dfs2 (wson[x], t);
	for (int i = pre[x]; i; i = a[i].next) {
		int v = a[i].to;
		if (v == fa[x] || v == wson[x]) continue;
		dfs2 (v, v);
	}
}
//线段树
void pushdown (int l, int r, int k) {
	if (cov[k] != maxn) {
		cov[k << 1] = cov[k << 1 | 1] = cov[k];
		ma[k << 1] = ma[k << 1 | 1] = cov[k];
	} else if (tag[k]) {
		if (cov[k << 1] != maxn) cov[k << 1] += tag[k];
		else tag[k << 1] += tag[k];
		if (cov[k << 1 | 1] != maxn) cov[k << 1 | 1] += tag[k];
		else tag[k << 1 | 1] += tag[k];
	}
	cov[k] = maxn;
	tag[k] = 0;
}
void build (int l, int r, int k) {
	cov[k] = maxn;
	if (l == r) {
		ma[k] = val[l];
		return;
	}
	int mid = l + r >> 1;
	build (l, mid, k << 1);
	build (mid + 1, r, k << 1 | 1);
	ma[k] = max (ma[k << 1], ma[k << 1 | 1]);
}
void upd (int l, int r, int k, int x, int y) {
	if (l == r) {
		tag[k] = 0;
		cov[k] = maxn;
		ma[k] = y;
		return;
	}
	int mid = l + r >> 1;
	if (x <= mid) upd (l, mid, k << 1, x, y);
	else upd (mid + 1, r, k << 1 | 1, x, y);
	ma[k] = max (ma[k << 1], ma[k << 1 | 1]);
}
void update (int f, int l, int r, int k, int x, int y, int z) {
	if (x <= l && y >= r) {
		if (f == 1) {
			tag[k] = 0;
			cov[k] = z;
			ma[k] = z;
		} else {
			if (cov[k] != maxn) cov[k] += z;
			else tag[k] += z;
			ma[k] += z;
		}
		return;
	}
	pushdown (l, r, k);
	int mid = l + r >> 1;
	if (x <= mid) update (f, l, mid, k << 1, x, y, z);
	if (y > mid) update (f, mid + 1, r, k << 1 | 1, x, y, z);
	ma[k] = max (ma[k << 1], ma[k << 1 | 1]);
}
int query (int l, int r, int k, int x, int y) {
	if (x <= l && y >= r) return ma[k];
	int mid = l + r >> 1, res = 0;
	pushdown (l, r, k);
	if (x <= mid) res = query (l, mid, k << 1, x, y);
	if (y > mid) res = max (res, query (mid + 1, r, k << 1 | 1, x, y) );
	return res;
}
//树链剖分
void Upd (int x, int y, int z, int f) {
	while (top[x] != top[y]) {
		if (dep[top[x] ] < dep[top[y] ]) swap (x, y);
		update (f, 1, n, 1, num[top[x] ], num[x], z);
		x = fa[top[x] ];
	}
	if (x == y) return;
	if (dep[x] > dep[y]) swap (x, y);
	update (f, 1, n, 1, num[x] + 1, num[y], z);
}
int q (int x, int y) {
	int ret = 0;
	while (top[x] != top[y]) {
		if (dep[top[x] ] < dep[top[y] ]) swap (x, y);
		ret = max (ret, query (1, n, 1, num[top[x] ], num[x]) );
		x = fa[top[x] ];
	}
	if (x == y) return ret;
	if (dep[x] > dep[y]) swap (x, y);
	return max (ret, query (1, n, 1, num[x] + 1, num[y]) );
}
int main () {
	dep[1] = 1;
	scanf ("%d", &n);
	for (int i = 1; i < n; i ++) {
		int u, v, w;
		scanf ("%d%d%d", &u, &v, &w);
		add (u, v, w);
		add (v, u, w);
	}
	dfs1 (1);
	dfs2 (1, 1);
	for (int i = 1; i < n; i ++) {
		int u = a[2 * i].from, v = a[2 * i].to, w = a[2 * i].len;
		if (fa[v] == u) swap (u, v);
		val[num[u] ] = w;
	}
	build (1, n, 1);
	char s[20];
	int x, y, z;
	while (1) {
		scanf ("%s", s);
		if (s[0] == 'S') break;
		scanf ("%d%d", &x, &y);
		if (s[0] == 'C' && s[1] == 'h') {
			int u = a[2 * x].from, v = a[2 * x].to;
			if (fa[v] == u) swap (u, v);
			upd (1, n, 1, num[u], y);
			continue;
		}
		if (s[0] != 'M') scanf ("%d", &z);
		if (s[0] == 'C') Upd (x, y, z, 1);
		else if (s[0] == 'A') Upd (x, y, z, 2);
		else cout << q (x, y) << "\n";
	}
	return 0;
}
2023/6/17 06:22
加载中...