BZOJ - 5457

题目链接: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;
}
发布了809 篇原创文章 · 获赞 246 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/105230153