C66 线段树合并 CF600E Lomsat Gelral

视频链接:252 线段树合并 CF600E Lomsat Gelral_哔哩哔哩_bilibili

 

 

CF600E Lomsat Gelral

#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

#define LL long long
#define mid ((l+r)>>1)
const int N=100005;
int n,col[N]; LL ans[N];
vector<int> g[N];
int root[N],tot; 
int ls[N*40],rs[N*40]; LL mx[N*40],sum[N*40];
// mx:主导颜色数, sum:主导颜色的编号和

void pushup(int u){ //上传
  if(mx[ls[u]]>mx[rs[u]])
    mx[u]=mx[ls[u]],sum[u]=sum[ls[u]];
  else if(mx[ls[u]]<mx[rs[u]])
    mx[u]=mx[rs[u]],sum[u]=sum[rs[u]];
  else
    mx[u]=mx[ls[u]],sum[u]=sum[ls[u]]+sum[rs[u]];
}
void change(int &u,int l,int r,int p,int k){ //点修
  if(!u) u=++tot; //开点
  if(l==r){mx[u]+=k;sum[u]=l;return;}
  if(p<=mid) change(ls[u],l,mid,p,k);
  else change(rs[u],mid+1,r,p,k);
  pushup(u);
}
int merge(int x,int y,int l,int r){ //合并
  if(!x||!y) return x+y;
  if(l==r){mx[x]+=mx[y];sum[x]=l;return x;}
  ls[x]=merge(ls[x],ls[y],l,mid);
  rs[x]=merge(rs[x],rs[y],mid+1,r);
  pushup(x);
  return x;
}
void dfs(int x, int f){ //递归合并
  for(int y:g[x]){
    if(y==f) continue;
    dfs(y,x);
    root[x]=merge(root[x],root[y],1,N);
  }
  change(root[x],1,N,col[x],1);
  ans[x]=sum[root[x]]; //及时保存,以免破坏
}
int main(){
  scanf("%d",&n);
  for(int i=1;i<=n;i++) scanf("%d",&col[i]); 
  for(int i=1,x,y; i<n; i++){
    scanf("%d%d",&x,&y);
    g[x].push_back(y); g[y].push_back(x);
  }
  dfs(1,0);
  for(int i=1;i<=n;i++)printf("%lld ",ans[i]);
}

  

posted @ 2023-11-10 21:24  董晓  阅读(171)  评论(0编辑  收藏  举报