1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| int read(){ char c=getchar(); int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x*f; }
const int N=1e5+10; // col[x]:节点的颜色编号, son[x]:重儿子, // cnt[i]:颜色编号i的数量 int n,col[N],siz[N],son[N],cnt[N],mx; LL sum,ans[N]; vector<int> e[N];
void dfs1(int x,int fa){ //重链剖分 siz[x]=1; for(int y : e[x]){ if(y==fa) continue; dfs1(y,x); siz[x]+=siz[y]; if(siz[y]>siz[son[x]]) son[x]=y; } } void add(int x,int fa,int son){ cnt[col[x]]++; if(cnt[col[x]]>mx) mx=cnt[col[x]],sum=col[x]; else if(cnt[col[x]]==mx) sum+=col[x]; for(int y : e[x]) //重子树除外 if(y!=fa && y!=son) add(y,x,son); } void sub(int x,int fa){ cnt[col[x]]--; for(int y : e[x]) if(y!=fa) sub(y,x); } void dfs2(int x, int fa, int opt){ for(int y : e[x]) //先搜轻儿子 if(y!=fa && y!=son[x]) dfs2(y,x,0); if(son[x]) dfs2(son[x],x,1); //后搜重儿子 add(x,fa,son[x]); //累加x和轻子树贡献 ans[x]=sum; //存储答案 if(!opt)sub(x,fa),sum=mx=0; //减掉轻子树贡献 } int main(){ n=read(); for(int i=1; i<=n; i++) col[i]=read(); for(int i=1; i<=n-1; i++){ int x=read(),y=read(); e[x].push_back(y); e[y].push_back(x); } dfs1(1,0); dfs2(1,0,0); for(int i=1; i<=n; i++) printf("%lld ",ans[i]); return 0; }
|