细节
当前节点的 \(2^i\) 号祖先等于\(2^{i-1}\)号祖先的 \(2^{i-1}\)号祖先,加法原理
for(int i=1;(1<<i)<=dep[u];i++)
f[u][i]=f[f[u][i-1]][i-1];
常数优化,O(n)预处理以2为底x的对数,在n较小的时候接受
for(int i=1;i<=n;i++)
lg[i]=lg[i-1]+(1<<(lg[i-1]+1)==i);
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
struct edge
{
int to,next;
}e[maxn<<1];
int head[maxn],f[maxn][30+5],lg[maxn],dep[maxn];
int size=0;
void init()
{
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
void addedge(int u,int v)
{
e[++size].to=v;
e[size].next=head[u];
head[u]=size;
}
void dfs(int u,int fa)//处理每个点信息:深度,祖先。
{
dep[u]=dep[fa]+1;
f[u][0]=fa;
for(int i=1;(1<<i)<=dep[u];i++)
f[u][i]=f[f[u][i-1]][i-1];
for(int i=head[u];i;i=e[i].next)
{
int to=e[i].to;
if(to==fa)continue;
dfs(to,u);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])
swap(x,y);
while(dep[x]>dep[y])
x=f[x][lg[dep[x]-dep[y]]];
if(x==y)return x;
for(int i=lg[dep[x]];i>=0;i--)
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return f[x][0];
}
int main()
{
//init();
int n=read(),m=read(),s=read();
for(int i=1;i<=n-1;i++)
{
int u=read(),v=read();
addedge(u,v);
addedge(v,u);
}
dfs(s,0);
for(int i=1;i<=n;i++)
lg[i]=lg[i-1]+(1<<(lg[i-1]+1)==i);
for(int i=1;i<=m;i++)
{
int x=read(),y=read();
printf("%d\n",lca(x,y));
}
return 0;
}