2021.8.10提高B组模拟2T2 祖孙询问(lca)(倍增)

Posted SSL_LKJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021.8.10提高B组模拟2T2 祖孙询问(lca)(倍增)相关的知识,希望对你有一定的参考价值。

祖孙询问

题目大意

输入样例

10
234  -1
12  234
13  234
14  234
15  234
16  234
17  234
18  234
19  234
233  19
5
234  233
233  12
233  13
233  15
233  19

输出样例

1
0
0
0
2

题目数据

解题思路

建出一棵树

在树上跑 lca(最近公共祖先)

如果 x,y 的 lca 为 x ,则 x 是 y 的祖先

lca 为 y,则 y 是 x 的祖先

否则为0

注:记得用倍增优化

AC代码

#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
int n,m,k,nn,tot,f[40005][20],deep[40005],head[40005];
struct node

	int to,next;
a[80005];
void add(int x,int y)

	a[++tot]=(node)y,head[x];
	head[x]=tot;

void dfs(int x)//先弄出来树,每个节点的深度

	for(int i=head[x];i;i=a[i].next)
	
		deep[a[i].to]=deep[x]+1;
		dfs(a[i].to);
	

int lca(int x,int y)//lca

	int ans;
	if(deep[x]<deep[y])ans=1,swap(x,y);
	else 
	
		if(deep[x]>deep[y])ans=2;
		else return 0;
	
	for(int i=nn;i>0;i--)
		if(deep[f[x][i]]>=deep[y])
			x=f[x][i];
	if(x!=y)return 0;
	return ans;

int main()

	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	
		int x,y;
		scanf("%d%d",&x,&y);
		if(y==-1)k=x;
		else f[x][1]=y,add(y,x);
	
	deep[k]=1;
	dfs(k);
	nn=log2(n)+1;//预处理
	for(int j=2;j<=nn;j++)
		for(int i=1;i<=40000;i++)
			f[i][j]=f[f[i][j-1]][j-1];
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
	
		int x,y;
		scanf("%d%d",&x,&y);
		printf("%d\\n",lca(x,y));
	
	return 0;

谢谢

以上是关于2021.8.10提高B组模拟2T2 祖孙询问(lca)(倍增)的主要内容,如果未能解决你的问题,请参考以下文章

2021.7.13提高B组模拟2T2 JIH的玩偶(倍增)

Jzoj 3054NOIP2012模拟10.27倍增祖孙询问

2021.8.10提高B组模拟2T1 单峰(快速幂)

2021.8.10提高B组模拟2T1 单峰(快速幂)

2021.8.10提高B组模拟2T4 数字(dp)

2021.8.10提高B组模拟2T3 比赛(二分)(贪心—前缀和)