CF 600 E. Lomsat gelral

E. Lomsat gelral

http://codeforces.com/contest/600/problem/E

题意:

  求每个子树内出现次数最多的颜色(如果最多的颜色出现次数相同,将颜色编号求和)。

分析:

  dsu on tree。

  这个可以解决一系列不带修改的子树查询问题。

  考虑暴力的思路:就是枚举每个子树,计算每个颜色出现的个数。统计答案。

  dsu on tree:最后一个子树枚举计算完了,它的贡献可以保留,然后用其它的子树去合并。(最后一棵子树是最大的)。现在的复杂度就是nlogn了。

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<cctype>
 7 #include<set>
 8 #include<vector>
 9 #include<queue>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13 
14 inline int read() {
15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
17 }
18 
19 const int N = 100005;
20 
21 int head[N], nxt[N << 1], to[N << 1], En;
22 int fa[N], siz[N], son[N], cnt[N], col[N], Mx;
23 LL ans[N], Sum;
24 
25 void add_edge(int u,int v) {
26     ++En; to[En] = v; nxt[En] = head[u]; head[u] = En;
27     ++En; to[En] = u; nxt[En] = head[v]; head[v] = En;
28 }
29 
30 void dfs(int u) {
31     siz[u] = 1;
32     for (int i=head[u]; i; i=nxt[i]) {
33         int v = to[i];
34         if (v == fa[u]) continue;
35         fa[v] = u;
36         dfs(v);
37         siz[u] += siz[v];
38         if (!son[u] || siz[son[u]] < siz[v]) son[u] = v;
39     }
40 }
41 
42 void add(int u) {
43     cnt[col[u]] ++;
44     if (cnt[col[u]] > Mx) Mx = cnt[col[u]], Sum = col[u];
45     else if (cnt[col[u]] == Mx) Sum += col[u];
46 }
47 void Calc(int u) {
48     add(u);
49     for (int i=head[u]; i; i=nxt[i]) 
50         if (to[i] != fa[u]) Calc(to[i]);
51 }
52 void Clear(int u) {
53     cnt[col[u]] --;
54     for (int i=head[u]; i; i=nxt[i]) 
55         if (to[i] != fa[u]) Clear(to[i]);
56 }
57 
58 void solve(int u,bool c) {
59     for (int i=head[u]; i; i=nxt[i]) 
60         if (to[i] != fa[u] && to[i] != son[u]) solve(to[i], 0);
61     if (son[u]) solve(son[u], 1);
62     add(u);
63     for (int i=head[u]; i; i=nxt[i]) 
64         if (to[i] != fa[u] && to[i] != son[u]) Calc(to[i]);
65     ans[u] = Sum;
66     if (!c) Clear(u), Mx = 0, Sum = 0;
67 }
68 
69 int main() {
70     int n = read();
71     for (int i=1; i<=n; ++i) col[i] = read();
72     for (int i=1; i<n; ++i) {
73         int u = read(), v = read(); 
74         add_edge(u, v);
75     }
76     dfs(1);
77     solve(1, 1);
78     for (int i=1; i<=n; ++i) printf("%I64d ",ans[i]);
79     return 0;
80 }

 

posted @ 2018-09-27 08:31  MJT12044  阅读(188)  评论(0编辑  收藏  举报