ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

长链剖分

2022-02-15 11:03:12  阅读:152  来源: 互联网

标签:hson 长链 剖分 int maxn quad 500010 root


算法简介

\(\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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有