长链剖分

变量

  • int dep[x]\texttt{int dep[x]}:节点 xx 的深度,其中根节点深度为 11
  • int mxd[x]\texttt{int mxd[x]}:以节点 xx 为根的子树的最大深度。
  • int Log[x]\texttt{int Log[x]}xx 二进制下的最高位。
  • int fa[x][j]\texttt{int fa[x][j]}:节点 xx2j2^j 级祖先。
  • int son[x]\texttt{int son[x]}:节点 xx 的重儿子。
  • int top[x]\texttt{int top[x]}:节点 xx 的链顶节点。
  • vector<int> up[x]\texttt{vector<int> up[x]}:链顶节点 xx 的向上节点的数组。
  • vector<int> dn[x]\texttt{vector<int> dn[x]}:链顶节点 xx 的向下节点的数组。

函数

  • void dfs1(int x)\texttt{void dfs1(int x)}:更新祖先、深度和重儿子等信息。
  • void dfs2(int x,int q)\texttt{void dfs2(int x,int q)}:更新 updnup、dn 数组。
  • int ask(int x,int k)\texttt{int ask(int x,int k)}:询问 xxkk 级祖先。
  • void init(int rt,int n)\texttt{void init(int rt,int n)}:初始化。

代码

struct LCD{
	int dep[N],mxd[N],Log[N],fa[N][21],son[N],top[N];
	vector<int>up[N],dn[N];
	void dfs1(int x){
		dep[x]=mxd[x]=dep[fa[x][0]]+1;
		for(int i=1;i<=19;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
		son[x]=-1;
		for(int i=0;i<e[x].size();i++){
			int y=e[x][i];
			if(y==fa[x][0])continue;
			dfs1(y);
			mxd[x]=max(mxd[x],mxd[y]);
			if(son[x]==-1||mxd[y]>mxd[son[x]])
				son[x]=y;
		}
	}
	void dfs2(int x,int q){
		top[x]=q;
		if(x==q){
			for(int i=0,f=x;i<=mxd[x]-dep[x];i++)
				up[x].push_back(f),f=fa[f][0];
			for(int i=0,f=x;i<=mxd[x]-dep[x];i++)
				dn[x].push_back(f),f=son[f];
		}
		if(son[x])dfs2(son[x],q);
		for(int i=0;i<e[x].size();i++){
			int y=e[x][i];
			if(y==son[x]||y==fa[x][0])continue;
			dfs2(y,y);
		}
	}
	int ask(int x,int k){
		if(!k)return x;
		x=fa[x][Log[k]];
		k-=(1<<Log[k]);
		k-=(dep[x]-dep[top[x]]);
		x=top[x];
		return k>=0?up[x][k]:dn[x][-k];
	}
	void init(int rt,int n){
		Log[0]=-1;
		for(int i=1;i<=n;i++)Log[i]=Log[i>>1]+1;
		dfs1(rt);dfs2(rt,rt);
	}
}lcd;
posted @ 2024-01-08 14:38  luckydrawbox  阅读(4)  评论(0)    收藏  举报  来源