Codeforces - F. Dominant Indices

题目链接:Codeforces - F. Dominant Indices


题目大意:1号节点为根,每个点的子树,某个深度节点最多的层数。如果多个相等,输出深度小的。

我们肯定由深度开始枚举,对每个子树线段树合并,然后权值线段树上面求值即可。

当然这道题也可 dsu on tree,但是常数比权值线段树大。

AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6+10;
int n,dep[N],m,res[N];
vector<int> v[N],g[N];
int rt[N],mx[N<<5],lc[N<<5],rc[N<<5],cnt;
void dfs(int x,int fa){
	dep[x]=dep[fa]+1;	m=max(m,dep[x]);	v[dep[x]].push_back(x);
	for(int i=0;i<g[x].size();i++){
		if(g[x][i]!=fa)	dfs(g[x][i],x);
	}
}
void change(int &p,int l,int r,int x){
	if(!p)	p=++cnt;
	if(l==r){mx[p]++;	return ;}
	int mid=l+r>>1;
	if(x<=mid)	change(lc[p],l,mid,x);
	else	change(rc[p],mid+1,r,x);
	mx[p]=max(mx[lc[p]],mx[rc[p]]);
}
int ask(int p,int l,int r){
	if(!p)	return 0;
	if(l==r)	return l;	int mid=l+r>>1;
	if(mx[lc[p]]==mx[p])	return ask(lc[p],l,mid);
	else	return ask(rc[p],mid+1,r);
}
int merge(int x,int y,int l,int r){
	if(!x||!y)	return x+y;
	if(l==r){mx[x]+=mx[y];	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);
	mx[x]=max(mx[lc[x]],mx[rc[x]]);
	return x;
}
signed main(){
	cin>>n;
	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,1);
	for(int i=m;i>=1;i--){
		for(int j=0;j<v[i].size();j++){
			int now=v[i][j];		change(rt[now],1,m,i);
			for(int k=0;k<g[now].size();k++){
				int to=g[now][k];
				if(dep[to]>dep[now])	merge(rt[now],rt[to],1,m);
			}
			res[now]=ask(rt[now],1,m)-i;
		}
	}
	for(int i=1;i<=n;i++)	printf("%d\n",res[i]);
	return 0;
}
发布了467 篇原创文章 · 获赞 241 · 访问量 2万+

猜你喜欢

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