题目描述
一个NN个节点的有根树(点11为根),节点从11到NN编号,每个节点有一个颜色C_iCi。
对于一个以xx为根的子树,我们认为颜色cc在这个子树中出现的次数是最多的,则认为cc支配了这个子树。
如果有多个颜色的次数相同并且都为最大,则他们都支配了这个子树。
对每个节点xx,输出所有支配他的子树的颜色的编号之和。
输入格式
第一行一个整数n,
接下来一行n个整数Ci,
接下来n-1行,每行两个整数x,y,表示x和y有一条边。
输出格式
输出一行n个数,第i个数为节点i的答案。
dsu on tree的入门题
十分套路的模板
(代码格式化真吼看)
#include <cstdio> #include <vector> using namespace std; void read(int &x) { char c = getchar(); x = 0; while (c < '0' || c > '9') c = getchar(); while ('0' <= c && c <= '9') x = x * 10 + c - 48, c = getchar(); } #define N 1000005 int n, siz[N], big[N], cr[N], c[N], mx; long long ans[N], sum; bool vis[N]; vector<int> g[N]; void dfs1(int x, int fa) { siz[x] = 1; for (auto i : g[x]) if (i != fa) { dfs1(i, x); siz[x] += siz[i]; if (siz[i] > siz[big[x]]) big[x] = i; } } void draw(int x, int fa, int k) { c[cr[x]] += k; if (k > 0 && c[cr[x]] >= mx) { if (c[cr[x]] > mx) sum = 0; mx = c[cr[x]]; sum += cr[x]; } for (auto i : g[x]) if (i != fa && !vis[i]) draw(i, x, k); } void dfs2(int x, int fa, bool is) { for (auto i : g[x]) if (i != fa && i != big[x]) dfs2(i, x, 0); if (big[x]) dfs2(big[x], x, 1), vis[big[x]] = 1; draw(x, fa, 1); ans[x] = sum; if (big[x]) vis[big[x]] = 0; if (!is) draw(x, fa, -1), sum = mx = 0; } int main() { read(n); for (int i = 1; i <= n; ++i) read(cr[i]); for (int i = 1, p, q; i < n; ++i) { read(p); read(q); g[p].push_back(q); g[q].push_back(p); } dfs1(1, 0); dfs2(1, 0, 1); for (int i = 1; i <= n; ++i) printf("%lld ", ans[i]); return 0; }