其他分享
首页 > 其他分享> > 长链剖分

长链剖分

作者:互联网

算法简介

\(\quad\)这个数据结构的重儿子是深度最深的节点,这是它和树链剖分唯一的区别。

\(\quad\)它最经典的应用就是求 k 级祖先,预处理的期望复杂度为 O(nlogn),查询 O(1)

\(\quad\)设每个节点的重儿子深度为 hson , 每个轻儿子记录往上 hson 长度路径的信息,每一条链头记录自己这条链的信息,都用 vector 存下来。

\(\quad\)查询就是先倍增跳,然后再利用 vector 的信息直接输出。

例题

Luogu 5903 树上k级祖先

 #include<bits/stdc++.h>
 using namespace std;
 const int maxn=500010;
 vector<int> g[maxn],up[maxn],down[maxn];
 int binh[500010],dep[500010],h[500010],hson[500010],tp[500010],fa[500010][20];
 struct 
 {
 	int nxt,v;
 }e[maxn];
 int head[maxn],cnt;
 unsigned int s;//题目中给的种子
inline unsigned int get(unsigned int x)//题目中给的随机函数
{
	x^=x<<13;
	x^=x>>17;
	x^=x<<5;
	return s=x; 
}
 void add(int u,int v)
 {
 	cnt++;
 	e[cnt].nxt=head[u];
 	e[cnt].v=v;
 	head[u]=cnt;
 }
 void dfs(int x,int f)
 {
 	dep[x]=dep[f]+1;
 	fa[x][0]=f;
 	for(int i=1;i<20;i++)
 	{
 		fa[x][i]=fa[fa[x][i-1]][i-1];
	 }
	 h[x]=-1;
	 for(int i=head[x];i;i=e[i].nxt)
	 {
	 	int v=e[i].v;
	 	if(v==f) continue ;
	 	dfs(v,x);
	 	if(h[v]>h[x])
	 	{
	 		hson[x]=v;
	 		h[x]=h[v];
		 }
	 }
	 h[x]++;
	 if(!h[x]) h[x]=1;
 }
 void dfs2(int x,int ttp)
 {
 	down[ttp].push_back(x);
 	tp[x]=ttp;
 	if(!hson[x]) return ;
 	dfs2(hson[x],ttp);
 	for(int i=head[x];i;i=e[i].nxt)
 	{
 		int v=e[i].v;
 		if(v!=hson[x] && v!=fa[x][0])
 		{
 			up[v].push_back(v);
 			for(int j=1;j<=h[v];j++)
 			{
 				up[v].push_back(fa[up[v].back()][0]);
			 }
			 dfs2(v,v);
		 }
	 }
 }
 int main()
 {
 	int n,q;
 	cin>>n>>q;
 	int root,x,k,lastans=0;
 	long long out=0;
 	cin>>s;
 	for(int i=1;i<=n;i++)
 	{
 		cin>>x;
 		if(!x) root=i;
 		else
 		{
 			add(x,i);
		 }
		 binh[i]=log2(i);
	 }
	 dfs(root,root);
	 dfs2(root,root);
	 for(int i=1;i<=q;i++)
	 {
	 	x=(get(s)^lastans)%n+1;
		k=(get(s)^lastans)%dep[x];
		if(!k)
		{
			lastans=x;
			out^=1ll*i*x;
			continue ;
		}
		int tod=dep[x]-k;
		x=tp[fa[x][binh[k]]];
		int tpd=dep[x];
		if(tpd<tod) x=down[x][tod-tpd];
		else x=up[x][tpd-tod];
		lastans=x;
		out^=1ll*i*x;
	 }
	 cout<<out;
 	return 0;
 }

注意

\(\quad\)尽管长链剖分的理论复杂度很优秀,但是在随机数据下有时还不如树剖LCA优秀,而且打起来也有点麻烦,所以一般情况不建议使用。但是如果询问很多的话,那长链剖分的优势就会体现出来。

标签:hson,长链,剖分,int,maxn,quad,500010,root
来源: https://www.cnblogs.com/SPzos017/p/15895441.html