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;
}
posted @ 2018-12-04 19:43  露迭月  阅读(290)  评论(0编辑  收藏  举报