luogu_3398_仓鼠找Sugar

题目略。

LCA题。

当满足题目要求的路径存在交叠的时候,必有一对点的LCA(设为点A)在另一对点(设为B,C)构造的路径上。

我们可以通过LCA计算A到B,C的距离,进行验证。

卡了2h没过结果是因为LOG表的预处理没写我真是服了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int N=100100;
int n,m,fa[N][20],dpt[N],LOG[N],head[N],tmp=0;
struct EDGE{int nxt,to;} edg[N<<1];
inline int read(){
	int x=0;char ch=getchar();
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') {x=x*10+ch-48;ch=getchar();}
	return x; 
}
inline void prepare_LOG(){
	int cnt=0;LOG[1]=0;
	for (int i=2;i<=n;++i){
		cnt+=((1<<(cnt+1))==i);
		LOG[i]=cnt;
	}
}
inline void build_tree(int now,int pre){
	dpt[now]=dpt[pre]+1;
	fa[now][0]=pre;
	for (int i=head[now];i;i=edg[i].nxt){
		int v=edg[i].to;
		if (v!=pre) build_tree(v,now);
	}
}
inline void add_edge(int u,int v) {
	edg[++tmp].nxt=head[u];
	edg[tmp].to=v; 
	head[u]=tmp;
}
inline void find_father(int x){
	for (int i=1;i<=LOG[dpt[x]];++i){
		fa[x][i]=fa[fa[x][i-1]][i-1];
	}
	for (int i=head[x];i;i=edg[i].nxt){
		int v=edg[i].to;
		if (v!=fa[x][0]) find_father(v);
	}
	return;
}
inline int LCA(int x,int y){
	if (dpt[x]<dpt[y]) swap(x,y);
	while (dpt[x]>dpt[y]) x=fa[x][LOG[dpt[x]-dpt[y]]];
	if (x==y) return x;
	for (int i=LOG[dpt[x]];i>=0;--i){
		if (fa[x][i]!=fa[y][i]) {x=fa[x][i];y=fa[y][i];}
	}
	return fa[x][0];
}
int main(){
	int i,j;
	memset(head,0,sizeof(head));
	n=read();m=read();
	for (i=1;i<n;++i) {
		int u=read(),v=read();
		add_edge(u,v);add_edge(v,u);
	}
	dpt[1]=1;
	prepare_LOG();
	build_tree(1,0);
	find_father(1);
	while (m--){
		int a=read(),b=read(),c=read(),d=read();
		int ast1=LCA(a,b),ast2=LCA(c,d),
			ast3=LCA(ast1,c),ast4=LCA(ast1,d),
			ast5=LCA(ast2,a),ast6=LCA(ast2,b);
		int LEN1=abs(dpt[a]-dpt[ast1])+abs(dpt[b]-dpt[ast1])+1,
			LEN2=abs(dpt[c]-dpt[ast2])+abs(dpt[d]-dpt[ast2])+1;
		int len1=abs(dpt[a]-dpt[ast5])+abs(dpt[ast2]-dpt[ast5])+abs(dpt[ast2]-dpt[ast6])+abs(dpt[b]-dpt[ast6])+1,
			len2=abs(dpt[c]-dpt[ast3])+abs(dpt[ast1]-dpt[ast3])+abs(dpt[ast1]-dpt[ast4])+abs(dpt[d]-dpt[ast4])+1;
//		printf("ast1=%d(ast3:%d,ast4:%d) ast2=%d(ast5:%d,ast6:%d)\n LEN1=%d LEN2=%d len1=%d len2=%d\n",ast1,ast3,ast4,ast2,ast5,ast6,LEN1,LEN2,len1,len2);
		if ((LEN1==len1)||(LEN2==len2)) puts("Y");else puts("N");
	}
	return 0;
}
posted @ 2020-09-26 17:11  O-GUYA  阅读(60)  评论(0编辑  收藏  举报
//接下来是那个华丽的鼠标点击效果代码!