轻重链剖分暴力。主要是skip数组有点蒙。
对于一个点A,一定是先把A的轻儿子先全部搜完然后搜A的重儿子。
轻儿子搜完之后记录都清空了。最后搜重儿子的时候搜完了要保留。if(son[u]) dfs(son[u],v,1),skip[son[u]]=1;通过skip保留。
然后是统计整个A的子树,这个时候calc就会把A的重儿子跳过。calc完了之后就得到ans[A]。
然后把A的重儿子的skip标记取消,这保证了:如果A是一个轻儿子,它整个子树的贡献都被清空。
我靠,要用long long。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=2e5+10;
int col[maxn],cnt[maxn];
int Head[maxn],Next[maxm],V[maxm],Cnt=1;
int son[maxn],sz[maxn],skip[maxn];
int n,x,y,mx;
long long sum,ans[maxn];
inline int read(){
int x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x;
}
inline void print(long long x){
if(x>9) print(x/10);
putchar(x%10+'0');
}
inline void add(int u,int v){
++Cnt;
Next[Cnt]=Head[u];
V[Cnt]=v;
Head[u]=Cnt;
}
void getson(int u,int f){
sz[u]=1,son[u]=0;
for(int i=Head[u];i;i=Next[i]){
if(V[i]==f) continue;
getson(V[i],u);
sz[u]+=sz[V[i]];
if(sz[son[u]]<sz[V[i]]) son[u]=V[i];
}
}
void calc(int u,int f,int val){
cnt[col[u]]+=val;
if(cnt[col[u]]>mx) sum=col[u],mx=cnt[col[u]];
else if(cnt[col[u]]==mx) sum+=col[u];
for(int i=Head[u];i;i=Next[i]){
if(V[i]==f||skip[V[i]]) continue;
calc(V[i],u,val);
}
}
void dfs(int u,int f,int keep){
int v;
for(int i=Head[u];i;i=Next[i]){
v=V[i];if(v==f||v==son[u]) continue;
dfs(v,u,0);
}
if(son[u]) dfs(son[u],u,1),skip[son[u]]=1;
calc(u,f,1),ans[u]=sum,skip[son[u]]=0;
if(!keep) calc(u,f,-1),sum=0,mx=0;
}
int main(){
n=read();
for(int i=1;i<=n;++i) col[i]=read();
for(int i=1;i<n;++i) x=read(),y=read(),add(x,y),add(y,x);
getson(1,0),dfs(1,0,1);
for(int i=1;i<=n;++i) print(ans[i]),putchar(' ');
}