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


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

  • 相关阅读:
    Cmake输出git内容方式
    Spring使用的注解大全和解释
    css3常见选择器
    mac版微信小程序反编译学习
    MySQL主从复制
    七牛云QRTC背后的质量提升实践
    对于小程序canvas在某些情况下touchmove 不能连续触发导致的签名不连续替代方案(企微)
    WinServer 2012 R2 搭建 AD 单域多站点
    多层感知机
    相机突然断电,保存的DAT视频文件如何修复
  • 原文地址:https://www.cnblogs.com/bingoyes/p/16584562.html