LCA 模板
LCA 模板
啊,为什么欧拉序,你的常数这样的大。
听说动态点分总是会想\(O(1)\)去求\(LCA\),今天来写一写。
然而不好写+常数大
会不会真香呢?
Code:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N=1<<21;
int head[N>>1],Next[N],to[N],cnt;
void add(int u,int v)
{
to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
int dep[N],dfn[N],turn[N],dfs_clock;
int n,m,rt;
struct node
{
int x,y;
bool friend operator <(node n1,node n2){return n1.x<n2.x;}
}f[N][21];
void dfs(int now,int fa)
{
f[++dfs_clock][0]={dep[now],now};
dfn[now]=dfs_clock;
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(v==fa) continue;
dep[v]=dep[now]+1;
dfs(v,now);
f[++dfs_clock][0]={dep[now],now};
}
}
using std::min;
void init()
{
for(int j=1;j<=20;j++)
{
for(int i=1<<j-1;i<min(dfs_clock+1,1<<j);i++)
turn[i]=j-1;
for(int i=1;i<=dfs_clock;i++)
f[i][j]=min(f[i][j-1],f[min(dfs_clock,i+(1<<j-1))][j-1]);
}
}
int LCA(int x,int y)
{
if(x>y) return LCA(y,x);
int d=turn[y+1-x];
return min(f[x][d],f[y-(1<<d)+1][d]).y;
}
int main()
{
scanf("%d%d%d",&n,&m,&rt);
for(int u,v,i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
memset(f,0x3f,sizeof(f));
dep[rt]=1;dfs(rt,rt);
init();
for(int x,y,i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",LCA(dfn[x],dfn[y]));
}
return 0;
}