CF600ELomsat gelral——树上启发式合并
Posted ty02
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF600ELomsat gelral——树上启发式合并相关的知识,希望对你有一定的参考价值。
(题面来自luogu)
题意翻译
一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和。
ci <= n <= 1e5
树上启发式合并裸题。统计时先扫一遍得到出现次数最大值,然后再扫一遍看哪个颜色的出现次数与mxCnt相等。注意用一个bool数组判重,清空轻儿子贡献时要顺手把bool数组也打成false。
代码:
- #include <iostream>
- #include <cstdio>
- #include <cctype>
- #define maxn 100010
- using namespace std;
- template <typename T>
- void read(T &x)
- x = 0;
- char ch = getchar();
- while (!isdigit(ch))
- ch = getchar();
- while (isdigit(ch))
- x = x * 10 + (ch ^ 48), ch = getchar();
- int n;
- int head[maxn], top;
- struct E
- int to, nxt;
- edge[maxn << 1];
- inline void insert(int u, int v)
- edge[++top] = (E) v, head[u];
- head[u] = top;
- int son[maxn], size[maxn];
- long long ans[maxn];
- void dfs1(int u, int pre)
- size[u] = 1;
- for (int i = head[u]; i; i = edge[i].nxt)
- int v = edge[i].to;
- if (v == pre) continue;
- dfs1(v, u);
- size[u] += size[v];
- if (size[v] > size[son[u]])
- son[u] = v;
- return;
- int color[maxn], cnt[maxn], sum;
- int curSon, mxCnt;
- bool vis[maxn];
- void calc(int u, int pre, bool op)
- op ? (++cnt[color[u]], mxCnt = max(mxCnt, cnt[color[u]])) : (--cnt[color[u]], vis[color[u]] = false);
- for (int i = head[u]; i; i = edge[i].nxt)
- int v = edge[i].to;
- if (v == pre || v == curSon)
- continue;
- calc(v, u, op);
- void stats(int u, int pre)
- if (cnt[color[u]] == mxCnt && !vis[color[u]])
- sum += color[u], vis[color[u]] = true;
- for (int i = head[u]; i; i = edge[i].nxt)
- int v = edge[i].to;
- if (v != pre)
- stats(v, u);
- return;
- void dsu(int u, int pre, bool op)
- for (int i = head[u]; i; i = edge[i].nxt)
- int v = edge[i].to;
- if (v == pre || v == son[u])
- continue;
- dsu(v, u, 0);
- if (son[u])
- dsu(son[u], u, 1), curSon = son[u];
- mxCnt = 0;
- calc(u, pre, 1);
- stats(u, pre);
- ans[u] = sum;
- curSon = 0;
- if (!op)
- sum = 0;
- calc(u, pre, 0);
- int main()
- read(n);
- for (int i = 1; i <= n; ++i)
- read(color[i]);
- int u, v;
- for (int i = 1; i < n; ++i)
- read(u), read(v);
- insert(v, u), insert(u, v);
- dfs1(1, 0);
- dsu(1, 0, 1);
- for (int i = 1; i <= n; ++i)
- printf("%I64d ", ans[i]);
- return 0;
交这个题的时候cf刚好炸了……
以上是关于CF600ELomsat gelral——树上启发式合并的主要内容,如果未能解决你的问题,请参考以下文章
CF600ELomset gelral 题解(树上启发式合并)
CF 600 E Lomsat gelral —— 树上启发式合并