CF1009F Dominant Indices

主要思想:长链剖分优化DP

洛谷题目传送门

给定一棵以 1 为根,n 个节点的树。设 d(u,x)u 子树中到 u 距离为 x 的节点数。

对于每个点,求一个最小的 k,使得 d(u,k) 最大。

数据范围 1e6


看到这题首先想到DP,对于一个点,需要合并的是它的所有子树同层的点个数,然而直接这样做会T飞 or M飞,考虑此题为子树信息合并,可以想到长链剖分优化DP,每次将一个点的子树的长链信息合并到当前点的长链上,每条链最多合并一次,复杂度神奇地降成 O(n)

优雅代码如下:

#include<bits/stdc++.h>
using namespace std;
inline int rd(){
	int f=1,j=0;
	char w=getchar();
	while(w>'9'||w<'0')w=getchar();
	while(w>='0'&&w<='9'){
		j=(j<<3)+(j<<1)+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=1000001;
int n,dep[N],d_dep[N];
int son[N],to[N],siz[N];
int ans[N],ans_siz[N];
vector<int>line[N];
void dfs1(int u,int fa){
	dep[u]=dep[fa]+1;
	d_dep[u]=dep[u];
	siz[u]=1;
	for(int x:line[u]){
		if(x==fa)continue;
		dfs1(x,u);
		if(d_dep[x]>d_dep[u]){
			d_dep[u]=d_dep[x];
			son[u]=x;
		}
	}
	to[u]=son[u];
	return ;
}
void merge(int x,int y){
	int u=x,len=1;x=to[x];
	while(y!=0){
		siz[x]+=siz[y];
		if(siz[x]>ans_siz[u]||(siz[x]==ans_siz[u]&&len<ans[u]))ans[u]=len,ans_siz[u]=siz[x];
		x=to[x];y=to[y];
		len++;
	}
	return ;
}
void dfs2(int u,int fa){
	if(son[u])dfs2(son[u],u);
	if(son[u]==0||ans[son[u]]==0)ans[u]=0,ans_siz[u]=1;
	else ans[u]=ans[son[u]]+1,ans_siz[u]=ans_siz[son[u]];
	for(int x:line[u]){
		if(x==fa||x==son[u])continue;
		dfs2(x,u);
		merge(u,x);
	}
	return ;
}
signed main(){
	n=rd();
	for(int i=1;i<n;i++){
		int x=rd(),y=rd();
		line[x].push_back(y);
		line[y].push_back(x);
	}
	dfs1(1,0);
	dfs2(1,0);
	for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
	return 0;
}
posted @   flywatre  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示