codeforces600E Lomsat gelral

Posted wfj_2048

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces600E Lomsat gelral相关的知识,希望对你有一定的参考价值。

题面:codeforces600E

 

学习一下$dsu \ on \ tree$。。

这个东西可以处理很多无修改子树问题,复杂度通常为$O(nlogn)$。

主要操作是:我们先把整棵树链剖一下,然后每次先递归轻儿子,再递归重儿子。

对于每棵子树,我们暴力加入整棵子树的贡献。如果是重儿子的子树则另外处理:加入贡献时不考虑加重儿子所在的子树,而在消除贡献时也不消除重儿子的子树,直到它成为某个点的轻儿子的子树的一部分时再消除贡献。

复杂度:因为每个轻儿子最多被加入$O(logn)$次(递归轻儿子时$size$至少$/2$),每条重链最多只会被加入$O(logn)$次,所以复杂度是$O(nlogn)$的。

说得有点玄学,还是看看代码吧。。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cstdio>
 7 #include <vector>
 8 #include <cmath>
 9 #include <queue>
10 #include <stack>
11 #include <map>
12 #include <set>
13 #define inf (1<<30)
14 #define N (200010)
15 #define il inline
16 #define RG register
17 #define ll long long
18 
19 using namespace std;
20 
21 struct edge{ int nt,to; }g[N<<1];
22 
23 int head[N],col[N],son[N],sz[N],c[N],n,num,Mx,flag;
24 ll ans[N],Sum;
25 
26 il int gi(){
27     RG int x=0,q=1; RG char ch=getchar();
28     while ((ch<0 || ch>9) && ch!=-) ch=getchar();
29     if (ch==-) q=-1,ch=getchar();
30     while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar();
31     return q*x;
32 }
33 
34 il void insert(RG int from,RG int to){
35     g[++num]=(edge){head[from],to},head[from]=num; return;
36 }
37 
38 il void dfs1(RG int x,RG int p){
39     sz[x]=1; RG int v;
40     for (RG int i=head[x];i;i=g[i].nt){
41     v=g[i].to; if (v==p) continue;
42     dfs1(v,x),sz[x]+=sz[v];
43     if (sz[son[x]]<=sz[v]) son[x]=v;
44     }
45     return;
46 }
47 
48 il void add(RG int x,RG int p,RG int val){
49     col[c[x]]+=val; RG int v;
50     if (Mx<col[c[x]]) Mx=col[c[x]],Sum=c[x];
51     else if (Mx==col[c[x]]) Sum+=c[x];
52     for (RG int i=head[x];i;i=g[i].nt){
53     v=g[i].to; if (v==p || v==flag) continue;
54     add(v,x,val);
55     }
56     return;
57 }
58 
59 il void dfs2(RG int x,RG int p,RG int fg){
60     RG int v;
61     for (RG int i=head[x];i;i=g[i].nt){
62     v=g[i].to; if (v!=p && v!=son[x]) dfs2(v,x,1);
63     }
64     if (son[x]) dfs2(son[x],x,0),flag=son[x];
65     add(x,p,1),flag=0,ans[x]=Sum;
66     if (fg) add(x,p,-1),Mx=Sum=0; return;
67 }
68 
69 int main(){
70 #ifndef ONLINE_JUDGE
71     freopen("600E.in","r",stdin);
72     freopen("600E.out","w",stdout);
73 #endif
74     n=gi();
75     for (RG int i=1;i<=n;++i) c[i]=gi();
76     for (RG int i=1,u,v;i<n;++i)
77     u=gi(),v=gi(),insert(u,v),insert(v,u);
78     dfs1(1,0),dfs2(1,0,1);
79     for (RG int i=1;i<=n;++i) printf("%I64d ",ans[i]);
80     return 0;
81 }

 

以上是关于codeforces600E Lomsat gelral的主要内容,如果未能解决你的问题,请参考以下文章

codeforces600E Lomsat gelral

Codeforces 600E - Lomsat gelral 「$Dsu on tree$模板」

CF600E Lomsat gelral(线段树合并)

600E - Lomsat gelral(找子树多颜色问题)(入门)

CF600E Lomsat gelral(树上启发式合并)

题解Lomsat gelral [CF600E]