• CF600E Lomsat gelral 题解


    solution

    看见统计所有子树的信息,想到线段树合并。对于一个节点,我们将它的所有子树合并上来,并更新出现次数最多的颜色和编号(如果有出现次数一样则将编号相加)即可。

    code

    #include <bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define I inline
    #define ll long long
    #define CI const int
    #define RI register int
    #define W while
    #define gc getchar
    #define D isdigit(c=gc())
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)<(y)?(x):(y))
    #define ms(a,x) memset((a),(x),sizeof(a))
    using namespace std;
    namespace SlowIO {
    	I void readc (char& c) {W (isspace (c = gc ()));}
    	Tp I void read (Ty& x) {char c; int f = 1; x = 0; W (! D) f = c ^ '-' ? 1 : -1; W (x = (x * 10) + (c ^ 48), D); x *= f;}
    	Ts I void read (Ty& x, Ar&... y) {read (x); read (y...);}
    } using namespace SlowIO;
    #define int long long
    CI N = 1e5, N2 = 2e5, N4 = 5e6; const ll MAX = 1e5; int sum[N4 + 5], ans[N4 + 5], sl[N4 + 5], sr[N4 + 5], c[N + 5], rt[N + 5], anss[N + 5], ntot = 0, n; // 注意多开内存,我开了60倍
    namespace graph {
    	int nxt[N2 + 5], to[N2 + 5], hd[N + 5], cnt = 0;
    	void add (int u, int v) {++ cnt; to[cnt] = v; nxt[cnt] = hd[u]; hd[u] = cnt;}
    } using namespace graph;
    void pushup (int root) { // 向上更新最多的颜色数量和编号
    	if (sum[sl[root]] > sum[sr[root]]) sum[root] = sum[sl[root]], ans[root] = ans[sl[root]];
    	else if (sum[sl[root]] < sum[sr[root]]) sum[root] = sum[sr[root]], ans[root] = ans[sr[root]];
    	else sum[root] = sum[sl[root]], ans[root] = ans[sl[root]] + ans[sr[root]]; // 记得相加编号
    }
    void update (int &root, int L, int R, int pos, int v) {
    	if (! root) root = ++ ntot; if (L == R) {ans[root] = L, sum[root] += v; return ;} int mid = (L + R) >> 1;
    	if (pos <= mid) update (sl[root], L, mid, pos, v); else update (sr[root], mid + 1, R, pos, v); pushup (root);
    }
    int merge (int a, int b, int L, int R) {
    	if (! a || ! b) return a + b; if (L == R) {sum[a] += sum[b]; ans[a] = L; return a;} int mid = (L + R) >> 1;
    	sl[a] = merge (sl[a], sl[b], L, mid); sr[a] = merge (sr[a], sr[b], mid + 1, R); pushup (a); return a;
    }
    void dfs (int now, int fa) { // 统计答案
    	for (int i = hd[now]; i; i = nxt[i]) {if (to[i] == fa) continue; dfs (to[i], now); merge (rt[now], rt[to[i]], 1, MAX);} update (rt[now], 1, MAX, c[now], 1); anss[now] = ans[rt[now]];
    }
    signed main () {
    	read (n); for (int i = 1; i <= n; ++ i) read (c[i]), rt[i] = i, ++ ntot; for (int i = 1; i < n; ++ i) {int u, v; read (u, v); add (u, v); add (v, u);} dfs (1, 0);
    	for (int i = 1; i <= n; ++ i) printf ("%lld ", anss[i]); printf ("\n");
    	return 0;
    }
    
  • 相关阅读:
    http和https
    openstack
    openstack安全问题
    openstack优势
    java多线程实现方式
    python多进程实现的几种方式
    Java 在提取url 生成图片以及正则表达式
    idea 生成 可执行文件
    dw cs6 支持高分辨率
    svchost.exe 大量占用的问题
  • 原文地址:https://www.cnblogs.com/ClapEcho233/p/16611310.html
Copyright © 2020-2023  润新知