codeforces600E Lomsat gelral【线段树合并/DSU】

第一次AC这道题,是三年前的一个下午,也许晚上也说不定。当时使用的\(DSU\) \(on\) \(tree\)算法,如今已经淡忘,再学习新的算法过程中,却与旧物重逢。生活中充满不可知会的相遇,即使重逢时多是物是人非。我又想起十六岁时在上海那个船上的夜晚,两岸的霓虹在无边黑暗中照亮了她的脸庞,绿衣在少年的眼瞳里凝滞了时间,那真是个美丽的夜晚,即使看不见星月。前天她给我说说点了个赞,我都高兴了好久,真是卑微呵。那么人世中所有明知卑微却不求告解的人,就是可悲吗?大抵是有更深沉的缘由的,比如最初的悸动从不属于初恋的对象,而是属于动情者的青葱。诗人和舔狗多少是有些区别的,虽然不多,而对于沿叶节点向根的路途,上面的答案会有下面的影响,所以至下而上一路合并即可。合并的过程中,若是同时抵达叶节点,两颗原本子树代表的颜色应该别无二致。树是权值的,一种颜色对应一个节点,所以\(dfs\)过程中针对颜色单点对应节点修改。至于关键的\(push\) \(up\),多者则独上,相同则齐加,生活亦然。

# include "bits/stdc++.h"
using namespace std;
constexpr int N = 1e5 + 3;
int main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	vector<int> col(n + 1);
	for(int i = 1; i <= n; ++i) cin >> col[i];
	vector G(n + 1, vector<int>());
	for(int i = 1; i < n; ++i) {
		int u, v;
		cin >> u >> v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	struct node {
		int l, r, tot;
		long long sum;
	};
	# define ls t[rt].l
	# define rs t[rt].r
	# define lson t[rt].l, l, mid
	# define rson t[rt].r, mid + 1, r
	vector<node> t(N * 50);
	auto push_up = [&](int rt) -> void {
		if(t[ls].tot == t[rs].tot) {
			t[rt].tot = t[ls].tot;
			t[rt].sum = t[ls].sum + t[rs].sum;
		}
		else if(t[ls].tot > t[rs].tot) {
			t[rt].tot = t[ls].tot;
			t[rt].sum = t[ls].sum;
		}
		else {
			t[rt].tot = t[rs].tot;
			t[rt].sum = t[rs].sum;
		}
	};
	vector<int> rt(n + 1, 0);
	int tree_index = n; // 1~n node has their names
	auto update = [&](auto update, int &rt, int l, int r, int x) -> void {
		if(!rt) rt = ++tree_index;
		if(l == r) {
			++t[rt].tot;
			t[rt].sum = l;
			return;
		}
		int mid = l + r >> 1;
		if(x <= mid)
			update(update, lson, x);
		else
			update(update, rson, x);
		push_up(rt);
	};
	auto merge = [&](auto merge, int x, int y, int l, int r) -> int {
		if(!x || !y) return x | y;
		if(l == r) {
			t[x].tot += t[y].tot;
			t[x].sum = l;
			return x;
		}
		int mid = l + r >> 1;
		t[x].l = merge(merge, t[x].l, t[y].l, l, mid);
		t[x].r = merge(merge, t[x].r, t[y].r, mid + 1, r);
		push_up(x);
		return x;
	};
	vector<long long> ans(n + 1);
	auto dfs = [&](auto dfs, int u, int father) -> void {
		for(auto v : G[u]) {
			if(v == father) continue;
			dfs(dfs, v, u);
			merge(merge, u, v, 1, n);
		}
		update(update, u, 1, n, col[u]);
		ans[u] = t[u].sum;
	};
	dfs(dfs, 1, 0);
	for(int i = 1; i <= n; ++i) cout << ans[i] << " ";
	return 0;
}

posted @ 2022-08-13 23:28  邱涵的秘密基地  阅读(182)  评论(0编辑  收藏  举报