关于长链剖分的数组实现 | CF1009F Dominant Indices

请容许我不理解一下为什么这题题解几乎全都是指针实现/kk
其实长链剖分是可以直接用数组来写的。

考虑朴素 DP。设 \(f_{u,i}\) 表示以点 \(u\) 为根的子树中与点 \(u\) 距离为 \(i\) 的点的个数。
则转移方程为:

\[f_{u,i}=\sum\limits_{v\in son_u} f_{v,i-1} \]

答案为:

\[ans_u=\max\{f_{u,i}\} \]

转移方程以深度为下标,可以使用长链剖分优化。

在重链剖分时,我们定义一个节点的重儿子为 \(siz\) 最大的儿子,而长链剖分时则是把能到达深度最深的点作为重儿子。
这样,每次我们先对于 \(u\) 的重儿子 DP,那么点 \(u\) 可以直接继承 \(son_u\) 的 DP 值,再暴力合并其它轻儿子。
对于每个点,只会在它所在长链的顶端被暴力合并一次,时间复杂度为 \(O(n)\)

观察到 \(f_v\) 在继承过来的时候是需要向后错一位的,这导致我们需要用一些特殊方法来存储 DP 值。
这里提供一种数组实现的思路。
对于 DP 数组 \(f\),我们把 \(f_{u,i}\) 映射到下标 \(dfn_u+i\) 的位置上。由于每次我们先遍历 \(son_u\),那么得到 \(dfn_{son_u}=dfn_u+1\)
也就是说,\(f_{v,0}\)\(f_{u,1}\) 映射的位置相同,恰好向后错了一位。
由于需要保证空间复杂度 \(O(n)\),在每求完一个点的 DP 值后统计该点的答案。

这个写法只是把一个指针数组换成了 \(dfn\) 数组,对空间复杂度似乎没啥影响(?)

#include<bits/stdc++.h>
#define il inline
using namespace std;
il int read()
{
	int xr=0,F=1; char cr=getchar();
	while(cr<'0'||cr>'9') {if(cr=='-') F=-1;cr=getchar();}
	while(cr>='0'&&cr<='9') 
		xr=(xr<<3)+(xr<<1)+(cr^48),cr=getchar();
	return xr*F;
}
const int N=1e6+5;
int n;
struct edge{
	int nxt,to;
}e[N<<1];
int head[N],cnt; 
void add(int u,int v){
	e[++cnt]={head[u],v};head[u]=cnt;
}
int dep[N],son[N],dfn[N],tot;
void dfs1(int now,int fa)
{
	for(int i=head[now];i;i=e[i].nxt)
	{
		int v=e[i].to;if(v==fa) continue;
		dfs1(v,now);
		if(dep[v]>dep[son[now]]) son[now]=v;
	}
	dep[now]=dep[son[now]]+1;
}
int f[N],ans[N]; 
void dfs2(int now,int fa)
{
	dfn[now]=++tot;
	f[dfn[now]]=1;
	if(son[now])
	{
		dfs2(son[now],now);
		if(f[dfn[son[now]]+ans[son[now]]]>1) ans[now]=ans[son[now]]+1;
	}
	for(int i=head[now];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if(v==son[now]||v==fa) continue;
		dfs2(v,now);
		for(int j=1;j<=dep[v];j++) 
		{
			f[dfn[now]+j]+=f[dfn[v]+j-1];
			if(f[dfn[now]+j]>f[dfn[now]+ans[now]]||
			f[dfn[now]+j]==f[dfn[now]+ans[now]]&&j<ans[now]) ans[now]=j;
		}
	}
}
int main()
{
	n=read();
	for(int i=1;i<n;i++)
	{
		int u=read(),v=read();
		add(u,v),add(v,u);
	}
	dfs1(1,0),dfs2(1,0);
	for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
	return 0;
}

upd:感觉这么搞局限性还是很大。指针还是该学学的。/kk

posted @ 2023-02-04 19:54  樱雪喵  阅读(73)  评论(0编辑  收藏  举报