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 }