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;
}
posted @ 2022-08-21 22:51  ClapEcho233  阅读(20)  评论(0编辑  收藏  举报