CF600E Lomsat gelral

cxqghzj·2023-11-14 16:37·4 次阅读

CF600E Lomsat gelral

题意#

给定一棵根为 1有根树

每个节点有颜色,求每个节点子树内出现最多的颜色编号之和。

Sol#

Dsu on tree板子题。

首先对于整棵树进行轻重链剖分,注意到一个关键性质:轻边只有 log

n2 的暴力是 trivial 的,不再赘述。

注意到中间有很多节点被重复计算了多次。

考虑如何减少重复计算的次数。

不难想到保留重儿子的贡献,每次重新计算轻儿子的贡献。

结合上述性质,不难发现时间复杂度为 O(nlogn)

Code#

Copy
#include <iostream> #include <algorithm> #include <cstdio> #include <array> #include <queue> #define int long long using namespace std; #ifdef ONLINE_JUDGE #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++) char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf; #endif int read() { int p = 0, flg = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') flg = -1; c = getchar(); } while (c >= '0' && c <= '9') { p = p * 10 + c - '0'; c = getchar(); } return p * flg; } void write(int x) { if (x < 0) { x = -x; putchar('-'); } if (x > 9) { write(x / 10); } putchar(x % 10 + '0'); } const int N = 1e5 + 5, M = 2e5 + 5; namespace G { array <int, N> fir; array <int, M> nex, to; int cnt; void add(int x, int y) { cnt++; nex[cnt] = fir[x]; to[cnt] = y; fir[x] = cnt; } } array <int, N> s; array <int, N> ans; namespace Dsu { using G::fir; using G::nex; using G::to; array <int, N> siz, dep, fa, son; array <int, N> dfn, idx; array <int, N> cur; queue <int> q; int tot, _ans; void add(int x) { cur[s[x]]++; q.push(s[x]); if (cur[s[x]] > tot) tot = cur[s[x]], _ans = s[x]; else if (cur[s[x]] == tot) _ans += s[x]; } void clear() { while (!q.empty()) cur[q.front()] = 0, q.pop(); tot = 0, _ans = 0; } int cnt; void dfs1(int x) { cnt++; idx[cnt] = x; dfn[x] = cnt; siz[x] = 1; for (int i = fir[x]; i; i = nex[i]) { if (to[i] == fa[x]) continue; fa[to[i]] = x; dep[to[i]] = dep[x] + 1; dfs1(to[i]); siz[x] += siz[to[i]]; if (siz[to[i]] > siz[son[x]]) son[x] = to[i]; } } void dfs2(int x) { for (int i = fir[x]; i; i = nex[i]) { if (to[i] == fa[x] || to[i] == son[x]) continue; dfs2(to[i]), clear(); } if (son[x]) dfs2(son[x]); for (int i = fir[x]; i; i = nex[i]) { if (to[i] == fa[x] || to[i] == son[x]) continue; for (int j = dfn[to[i]]; j <= dfn[to[i]] + siz[to[i]] - 1; j++) add(idx[j]); } add(x); ans[x] += _ans; } } signed main() { int n = read(); for (int i = 1; i <= n; i++) s[i] = read(); for (int i = 2; i <= n; i++) { int x = read(), y = read(); G::add(x, y), G::add(y, x); } Dsu::dfs1(1), Dsu::dfs2(1); for (int i = 1; i <= n; i++) write(ans[i]), putchar(32); puts(""); return 0; }
posted @   cxqghzj  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
目录