题意:给你一棵有 nn 个点的树 (nleq10^5)(n≤105) ,树上每个节点都有一种颜色 ci(cileq n)ci(ci≤n) ,让你求每个点子树出现最多的颜色的 颜色编号 的和
线段树合并可以维护子树的所有线段树之和
权值线段维护一下出现最多的数字即可
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=2e6+10; ll sum[N<<2],t[N<<2],anss[N]; int lson[N<<2],rson[N<<2],ncnt,pos,head[N],c[N],n,T[N]; void up(int pos) { if(sum[lson[pos]]>sum[rson[pos]]) { sum[pos]=sum[lson[pos]]; t[pos]=t[lson[pos]]; } else if(sum[lson[pos]]<sum[rson[pos]]) { sum[pos]=sum[rson[pos]]; t[pos]=t[rson[pos]]; } else if(sum[lson[pos]]==sum[rson[pos]]) { sum[pos]=sum[lson[pos]]; t[pos]=t[lson[pos]]+t[rson[pos]]; } } void upnode(int x,int l,int r,int &pos) { if(!pos)pos=++ncnt; if(l==r){sum[pos]+=1;t[pos]=l;return ;} int m=(l+r)>>1; if(x<=m)upnode(x,l,m,lson[pos]); else upnode(x,m+1,r,rson[pos]); up(pos); } int Merge(int a,int b,int l,int r) { if(!a)return b; if(!b)return a; if(l==r) { sum[a]+=sum[b]; t[a]=l; return a; } int m=(l+r)>>1; lson[a]=Merge(lson[a],lson[b],l,m); rson[a]=Merge(rson[a],rson[b],m+1,r); up(a);return a; } struct Edge{int to,nex;}edge[N]; void add(int a,int b){edge[++pos]=(Edge){b,head[a]};head[a]=pos;} void dfs(int x,int fa) { for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to; if(v==fa)continue; dfs(v,x);//注意 这里是 先更新 然后再合并 Merge(T[x],T[v],1,1e5); } upnode(c[x],1,100000,T[x]); anss[x]=t[T[x]]; } int main() { cin>>n; rep(i,1,n)scanf("%d",&c[i]),ncnt++,T[i]=i; rep(i,1,n-1) { int x,y;scanf("%d%d",&x,&y); add(x,y);add(y,x); } dfs(1,0); rep(i,1,n) printf("%lld ",anss[i]); return 0; }