【CF1009F】Dominant Indices

题目

长链剖分板子题啊

长链剖分有几个神奇的性质

  1. 所有长链的总点数为\(n\)

  2. 任意一个点的\(k\)级祖先所在长链的长度肯定不小于\(k\)

  3. 从任意点到根经过的短边数量不超过\(\sqrt{n}\),也就是用长链剖分求\(LCA\)是根号复杂度的。。

最后一个性质是这样的,从一个点往上经过一条短边,点数要加\(1\),再经过一条短边,点数要加\(2\),经过一共\(k\)条短边,点数要加\(\frac{k(k+1)}{2}\),于是短边次数就是\(\sqrt{n}\)级别的

之后长链剖分可以\(O(1)\)\(k\)级祖先,不过好像没什么用啊,最主要的作用还是用来优化一些树上跟深度有关系的转移,可以做到均摊\(O(n)\)复杂度

比如说这道题我们设\(f[x][j]\)表示在\(x\)的子树中距离\(x\)深度为\(j\)的点有多少个

我们需要另\(x\)直接继承其长儿子的状态,就是\(f[x][j+1]=f[son[x]][j]\),这个需要用指针\(O(1)\)实现

之后对于所有的短儿子,我们直接暴力合并过去

我们发现这样之后在一个点不是其父亲的长儿子的时候会暴力合并,代价是这条长链的长度,根据性质\(1\),所有长链的长度为\(n\),所以这个算法是均摊\(O(n)\)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const int maxn=1000005;
inline int read() {
	char c=getchar();int x=0;while(c<'0'||x>'9') c=getchar();
	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
struct E{int v,nxt;}e[maxn<<1];
int head[maxn],deep[maxn],len[maxn],son[maxn];
int n,num,tax[maxn],*id=tax,*f[maxn],ans[maxn];
inline void add(int x,int y) {
	e[++num].v=y;e[num].nxt=head[x];head[x]=num;
}
void dfs1(int x) {
	int maxx=-1;
	for(re int i=head[x];i;i=e[i].nxt) {
		if(deep[e[i].v]) continue;
		deep[e[i].v]=deep[x]+1;
		dfs1(e[i].v);
		if(len[e[i].v]>maxx) maxx=len[e[i].v],son[x]=e[i].v;
	}
	len[x]=len[son[x]]+1;
}
void dfs(int x) {
	f[x][0]=1;
	if(son[x]) f[son[x]]=f[x]+1,dfs(son[x]),ans[x]=ans[son[x]]+1;
	for(re int i=head[x];i;i=e[i].nxt) {
		if(deep[e[i].v]<deep[x]||e[i].v==son[x]) continue;
		f[e[i].v]=id;id+=len[e[i].v];dfs(e[i].v);
		for(re int j=1;j<=len[e[i].v];j++) {
			f[x][j]+=f[e[i].v][j-1];
			if(f[x][j]>f[x][ans[x]]||(f[x][j]==f[x][ans[x]]&&j<ans[x]))
				ans[x]=j;
		}
	}
	if(f[x][ans[x]]==1) ans[x]=0;
}
int main() {
	n=read();
	for(re int x,y,i=1;i<n;i++)
		x=read(),y=read(),add(x,y),add(y,x);
	deep[1]=1,dfs1(1);
	f[1]=id,id+=len[1];dfs(1);
	for(re int i=1;i<=n;i++) printf("%d\n",ans[i]);
	return 0;
}
posted @ 2019-04-09 09:49  asuldb  阅读(188)  评论(0编辑  收藏  举报