zoukankan      html  css  js  c++  java
  • LCA ST表

    //LCA
    //ST表 在线 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #define maxn 500001
    using namespace std;
    int n,m,cnt,root,head[maxn],depth[maxn];
    int order[2*maxn],first[maxn];//order[x]dfs中第x次遍历的点(重复) first[x]记录点x在dfs中首次遍历顺序(不重复) 
    int lg[2*maxn],f[2*maxn][21];//lg[x]记录log2x的向下取整值  f[x][k]表示包含x点共2^k个点中最小值 
    struct uio{
        int next,to;
    }edge[2*maxn];
    void add(int x,int y)
    {
        edge[++cnt].next=head[x];
        edge[cnt].to=y;
        head[x]=cnt;
    }
    void dfs(int x,int pre)//pre为上次遍历过节点 防止走重 
    {
        order[++cnt]=x;
        first[x]=cnt;
        for(int i=head[x];i!=-1;i=edge[i].next)
        {
            int u=edge[i].to;
            if(u!=pre)
            {
                depth[u]=depth[x]+1;
                dfs(u,x);
                order[++cnt]=x;
            }
        } 
    } 
    void ST()
    {
        for(int i=1;i<=cnt;i++)
            f[i][0]=order[i];
        lg[1]=0,lg[2]=1;
        for(int i=3;i<=cnt;i++)
        {
            lg[i]=lg[i-1];
            if(1<<lg[i-1]+1==i)
                lg[i]++;
        }
        int num=lg[cnt];
        for(int j=1;j<=num;j++)
            for(int i=1;i+(1<<j)-1<=cnt;i++)// i+(1<<j)-1 -1原因:区间包括自身 
            {
                if(depth[f[i][j-1]]<depth[f[i+(1<<j-1)][j-1]])
                    f[i][j]=f[i][j-1];
                else
                    f[i][j]=f[i+(1<<j-1)][j-1];
            }
    }
    int    RMQ(int l,int r)
    {
        int k=lg[r-l+1];
        if(depth[f[l][k]]<depth[f[r-(1<<k)+1][k]])//r-(1<<k)+1 +1原因:区间包括自身 
            return f[l][k];
        else return f[r-(1<<k)+1][k];//此处+1原因同上 
    }
    int ask(int x,int y)
    {
        x=first[x];
        y=first[y];
        if(x>y)
            swap(x,y);
        return RMQ(x,y);
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&root);
        memset(head,-1,sizeof(head));
        for(int i=1;i<=n-1;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        cnt=0;
        dfs(root,-1);
        ST();
        for(int i=1;i<=m;i++)
        {
            int u,v;
            scanf("%d %d",&u,&v);
            printf("%d
    ",ask(u,v));
        }
        return 0;
    }
  • 相关阅读:
    git rebase解决合并冲突
    Google GMS介绍
    MTK Android修改System分区
    Adb adb push (remote write failed: No space left on device)
    Android Visibility控件显示和隐藏
    MTK Android中设置默认时区
    初级Oracle和SQL学习者的学习笔记。韩顺平-玩转oracle。
    网络知识从零开始一:私有地址。
    oracle中有关用户、角色的一些概念。
    oracle中的一些函数笔记
  • 原文地址:https://www.cnblogs.com/water-radish/p/9280507.html
Copyright © 2011-2022 走看看