codeforces 1009F. Dominant Indices(长链剖分)

传送门
长链剖分模板题。
题意:给出一棵树,设 f i , j f_{i,j} fi,j表示 i i i的子树中距离点 i i i距离为 j j j的点的个数,现在对于每个点 i i i要求出使得 f i f_i fi取得最大值的那个 j j j


思路:有一个明显的状态转移式 f i , j = ∑ v ∈ s o n i f v , j − 1 f_{i,j}=\sum_{v\in son_i}f_{v,j-1} fi,j=vsonifv,j1,那么考虑对这棵树长链剖分,对于链上的信息用指针实现 O ( 1 ) O(1) O(1)转移,而链与链之间的转移直接暴力转就行,因为总的链长是 O ( n ) O(n) O(n)的因此这样做时间复杂度也为 O ( n ) O(n) O(n)
代码:

#include
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=1e6+5;
int n,ftmp[N<<1],*f[N],*now=ftmp,hson[N],mdep[N],len[N],dep[N],fa[N],ans[N];
vector<int>e[N];
void dfs1(int p){
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa[p])continue;
		fa[v]=p,dep[v]=mdep[v]=dep[p]+1,dfs1(v),mdep[p]=max(mdep[p],mdep[v]);
		if(mdep[v]>mdep[hson[p]])hson[p]=v;
	}
	len[p]=mdep[p]-dep[p]+1;
}
void dfs2(int p){
	if(hson[p])f[hson[p]]=f[p]+1,dfs2(hson[p]),ans[p]=ans[hson[p]]+1;
	f[p][0]=1;
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa[p]||v==hson[p])continue;
		f[v]=now,now+=len[v]+1,dfs2(v);
		for(ri i=1;i<=len[v];++i){
			f[p][i]+=f[v][i-1];
			if((i<ans[p]&&f[p][i]>=f[p][ans[p]])||(i>ans[p]&&f[p][i]>f[p][ans[p]]))ans[p]=i;
		}
	}
	if(f[p][ans[p]]==1)ans[p]=0;
}
int main(){
	n=read();
	for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
	dfs1(1),f[1]=now,now+=len[1],dfs2(1);
	for(ri i=1;i<=n;++i)cout<<ans[i]<<'\n';
	return 0;
}

你可能感兴趣的:(#,树链剖分,#,长链剖分)