社区讨论

为何根节点深度从0开始80分.从1开始100分

P4556【模板】线段树合并 / [Vani 有约会] 雨天的尾巴参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@lo8in5do
此快照首次捕获于
2023/10/27 19:14
2 年前
此快照最后确认于
2023/10/27 19:14
2 年前
查看原帖

RT, 下面是80分代码, 把dep[1]\rm dep[1]初始化为1就ac了

CPP
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
const int N = 1e5 + 5;

struct SegmentTree {
	int tot;
	vector< int > ls, rs, rub;
	vector< i64 > cnt, col;

	SegmentTree() : ls(N << 6), rs(ls), cnt(N << 6), col(cnt), tot(0) {}
	// 动态开点
	void New(int &x) {
		if (!rub.empty()) {
			x = rub.back();
			rub.pop_back();
		} else {
			x = ++ tot;
		}
	}
	// 删除节点
	void Delete(int &x) {
		ls[x] = rs[x] = cnt[x] = 0;
		rub.push_back(x);
		x = 0;
	}
	void Push_Up(int x) {
		cnt[x] = max(cnt[ls[x]], cnt[rs[x]]);
		col[x] = cnt[ls[x]] >= cnt[rs[x]] ? col[ls[x]] : col[rs[x]];
	}
	// 使线段树x里权值为pos的个数增加k
	void Modify(int &x, int l, int r, int pos, i64 k) {
		if (!x) {
			New(x);
		}
		if (l == r) {
			cnt[x] += k;
			col[x] = l;
			return;
		}
		int mid = (l + r) >> 1;
		if (pos <= mid) {
			Modify(ls[x], l, mid, pos, k);
		} else {
			Modify(rs[x], mid + 1, r, pos, k);
		}
		Push_Up(x);
	}
	// 将线段树y合并到线段树x,并销毁线段树y
	void Merge(int &x, int &y, int l, int r) {
		if (!x || !y) {
			x += y;
			return;
		}
		if (l == r) {
			cnt[x] += cnt[y];
			col[x] = l;
			Delete(y);
			return;
		}
		int mid = (l + r) >> 1;
		Merge(ls[x], ls[y], l, mid);
		Merge(rs[x], rs[y], mid + 1, r);
		Push_Up(x);
	}
};
int n, m;
vector< int > adj[N];
int t, dep[N], f[N][20];
void dfs(int x, int p) {
	for (int i = 1; i <= t; ++ i) {
		f[x][i] = f[f[x][i - 1]][i - 1];
	}
	for (auto &y : adj[x]) {
		if (y != p) {
			dep[y] = dep[x] + 1;
			f[y][0] = x;
			dfs(y, x);
		}
	}
}
int LCA(int x, int y) {
	if (dep[x] > dep[y]) {
		swap(x, y);
	}
	for (int i = t; i >= 0; -- i) {
		if (dep[f[y][i]] >= dep[x]) {
			y = f[y][i];
		}
	}
	if (x == y) {
		return x;
	}
	for (int i = t; i >= 0; -- i) {
		if (f[x][i] != f[y][i]) {
			x = f[x][i];
			y = f[y][i];
		}
	}
	return f[x][0];
}
int ans[N], rt[N];
signed main() {
	cin.tie(nullptr)->sync_with_stdio(false);

	cin >> n >> m;
	for (int i = 1; i < n; ++ i) {
		int u, v;
		cin >> u >> v;
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	t = ceil(log2(n));
	dfs(1, 0);
	SegmentTree st;
	while (m -- ) {
		int x, y, z;
		cin >> x >> y >> z;
		int fa = LCA(x, y), fafa = f[fa][0];
		st.Modify(rt[x], 1, N, z, 1);
		st.Modify(rt[y], 1, N, z, 1);
		st.Modify(rt[fa], 1, N, z, -1);
		st.Modify(rt[fafa], 1, N, z, -1);
	}
	function< void(int, int) > calc = [&] (int x, int p) {
		for (auto &y : adj[x]) {
			if (y != p) {
				calc(y, x);
				st.Merge(rt[x], rt[y], 1, N);
			}
		}
		if (st.cnt[rt[x]]) {
			ans[x] = st.col[rt[x]];
		}
	};
	calc(1, 0);
	for (int i = 1; i <= n; ++ i) {
		cout << ans[i] << '\n';
	}
	return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...