一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,如果一个子树中某种颜色的出现次数最多,则称这棵子树被这种颜色占领(可能被多种颜色占领),问以每一个节点为根的子树,占领它的颜色的编号之和
这题的做法好像是一个叫做dsu on tree的东西(dsu似乎是并查集的缩写?然而和并查集没什么关系啊……)
这题目虽然dfs序套莫队也能做,不过我们考虑一下暴力的方法
我们在统计节点u之前,把u的所有子树的贡献都加入答案,然后在暴力把所有的贡献都清楚
然而这样会有很多的无用的删除操作
我们考虑先把原树给轻重链剖分,然后统计子树贡献的时候,在处理完轻儿子的答案之后,把他们的影响给消除,但处理完重儿子的答案之后,不必把影响消除
这样的话顺序就是先处理轻儿子的答案并消除影响,然后处理重儿子,保留影响,再去处理一遍轻儿子来求出当前子树的答案
因为轻重链剖分之后一个点到根的路径上最多有$O(logn)$条轻边,所以每个节点只会被统计与删除$O(logn)$次,总复杂度就是$O(nlogn)$
板子(?)抄zcy的
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #define ll long long 5 using namespace std; 6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 7 char buf[1<<21],*p1=buf,*p2=buf; 8 int read(){ 9 #define num ch-'0' 10 char ch;bool flag=0;int res; 11 while(!isdigit(ch=getc())) 12 (ch=='-')&&(flag=true); 13 for(res=num;isdigit(ch=getc());res=res*10+num); 14 (flag)&&(res=-res); 15 #undef num 16 return res; 17 } 18 char sr[1<<21],z[20];int C=-1,Z; 19 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 20 void print(ll x){ 21 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 22 while(z[++Z]=x%10+48,x/=10); 23 while(sr[++C]=z[Z],--Z);sr[++C]=' '; 24 } 25 const int N=2e5+5; 26 int head[N],Next[N<<1],ver[N<<1],tot; 27 void add(int u,int v){ 28 ver[++tot]=v,Next[tot]=head[u],head[u]=tot; 29 } 30 int n,c[N],val[N],sz[N],son[N];ll ans[N]; 31 void dfs1(int u,int fa=0){ 32 sz[u]=1; 33 for(int i=head[u];i;i=Next[i]){ 34 int v=ver[i]; 35 if(v!=fa){ 36 dfs1(v,u),sz[u]+=sz[v]; 37 if(sz[son[u]]<sz[v]) son[u]=v; 38 } 39 } 40 } 41 bool vis[N];int mx=0;ll sum=0; 42 void update(int u,int fa,int k){ 43 c[val[u]]+=k; 44 if(k>0&&c[val[u]]>=mx){ 45 if(c[val[u]]>mx) sum=0,mx=c[val[u]]; 46 sum+=val[u]; 47 } 48 for(int i=head[u];i;i=Next[i]) 49 if(ver[i]!=fa&&!vis[ver[i]]) update(ver[i],u,k); 50 } 51 void dfs2(int u,int fa=0,bool used=0){ 52 for(int i=head[u];i;i=Next[i]){ 53 int v=ver[i];if(v!=fa&&v!=son[u]) dfs2(v,u); 54 } 55 if(son[u]) dfs2(son[u],u,1),vis[son[u]]=1; 56 update(u,fa,1),ans[u]=sum; 57 if(son[u]) vis[son[u]]=0; 58 if(!used) update(u,fa,-1),mx=sum=0; 59 } 60 int main(){ 61 // freopen("testdata.in","r",stdin); 62 n=read(); 63 for(int i=1;i<=n;++i) val[i]=read(); 64 for(int i=1;i<n;++i){ 65 int u=read(),v=read();add(u,v),add(v,u); 66 } 67 dfs1(1),dfs2(1); 68 for(int i=1;i<=n;++i) print(ans[i]); 69 return Ot(),0; 70 }