题目链接:BZOJ - 5457
直接线段树合并,下标为种族,权值为个数,维护最大值即可。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=4e5+10,M=N*40;
int n,m,a[N],b[N],rt[N],mx[M],id[M],lc[M],rc[M],cnt,res1[N],res2[N];
vector<int> g[N];
inline void add(int a,int b){g[a].push_back(b),g[b].push_back(a);}
void change(int &p,int l,int r,int x,int v){
if(!p) p=++cnt;
if(l==r){mx[p]+=v; id[p]=l; return ;}
int mid=l+r>>1;
if(x<=mid) change(lc[p],l,mid,x,v);
else change(rc[p],mid+1,r,x,v);
if(mx[lc[p]]>=mx[rc[p]]) id[p]=id[lc[p]],mx[p]=mx[lc[p]];
else id[p]=id[rc[p]],mx[p]=mx[rc[p]];
}
int merge(int x,int y,int l,int r){
if(!x||!y) return x^y;
if(l==r){mx[x]+=mx[y]; id[x]=l; return x;}
int mid=l+r>>1;
lc[x]=merge(lc[x],lc[y],l,mid);
rc[x]=merge(rc[x],rc[y],mid+1,r);
if(mx[lc[x]]>=mx[rc[x]]) id[x]=id[lc[x]],mx[x]=mx[lc[x]];
else id[x]=id[rc[x]],mx[x]=mx[rc[x]];
return x;
}
void dfs(int x,int fa){
change(rt[x],1,m,a[x],b[x]);
for(int i=0;i<g[x].size();i++){
int to=g[x][i]; if(to==fa) continue;
dfs(to,x); rt[x]=merge(rt[x],rt[to],1,m);
}
res1[x]=id[rt[x]],res2[x]=mx[rt[x]];
}
signed main(){
scanf("%d %d",&n,&m);
for(int i=1,a,b;i<n;i++) scanf("%d %d",&a,&b),add(a,b);
for(int i=1;i<=n;i++) scanf("%d %d",&a[i],&b[i]);
dfs(1,1);
for(int i=1;i<=n;i++) printf("%d %d\n",res1[i],res2[i]);
return 0;
}