• 区间节点的lca


    题目hdu5266

    分析:多节点的LCA就是dfs序中最大最小两个节点的LCA。所以只要每次维持给出节点的dfs序的最大最小,然后就是两点的LCA

    代码:

    rmq的st+lca的倍增

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<math.h>
    //#include<bits/stdc++.h>
    using namespace std;
    const int max_=311111;
    int n;
    int edge[max_*2];
    bool vis[max_];
    int deep[max_];
    int p[max_][25];
    int dp_min[max_][25];
    int dp_max[max_][25];
    int a[max_];
    //int smax[max_][25],smin[max_][23];
    int tot,idx;
    void init()
    {
        tot=0;
        memset(edge,-1,sizeof(edge));
        idx=0;
        memset(vis,0,sizeof(vis));
        memset(deep,0,sizeof(deep));
        memset(p,-1,sizeof(p));
    }
    struct tree{
        int to;
        int next;
    }G[max_*2];
    
    void add_edge(int u,int v)
    {
        G[++tot].to=v;
        G[tot].next=edge[u];
        edge[u]=tot;
    }
    void dfs(int u)
    {
        vis[u]=1;
        a[u-1]=idx++;
        for(int i=edge[u];~i;i=G[i].next)
        {
            int v=G[i].to;
            if(!vis[v])
            {
                p[v][0]=u;
                deep[v]=deep[u]+1;
                dfs(v);
            }
        }
    }
    int Max(int x,int y)
    {
        if(a[x]>a[y])
            return x;
        else
            return y;
    }
    int Min(int x,int y)
    {
        if(a[x]>a[y])
            return y;
        else
            return x;
    }
    void st_init()
    {
        for(int i=0;i<n;i++)
        {
            dp_max[i][0]=i,
            dp_min[i][0]=i;
        }
        for(int j=1;(1<<j)<=n;j++)
            for(int i=0;i+(1<<j)-1<n;i++)
        {
            dp_max[i][j]=Max(dp_max[i][j-1],dp_max[i+(1<<(j-1))][j-1]);
            dp_min[i][j]=Min(dp_min[i][j-1],dp_min[i+(1<<(j-1))][j-1]);
        }
    }
    int st_q_max(int l,int r)
    {
        int k=0;
        while((1<<(k+1))<=r-l+1)
            k++;
        return Max(dp_max[l][k],dp_max[r-(1<<k)+1][k]);
    }
    int st_q_min(int l,int r)
    {
        int k=0;
        while((1<<(k+1))<=r-l+1)
            k++;
        return Min(dp_min[l][k],dp_min[r-(1<<k)+1][k]);
    }
    void lca_init()
    {
        for(int j=1;(1<<j)<=n;j++)
            for(int i=1;i<=n;i++)
            if(~p[i][j-1])
            p[i][j]=p[p[i][j-1]][j-1];
    }
    int lca(int u,int v)
    {
       if(deep[u]<deep[v])//u_max;
            swap(u,v);
       int k=deep[u]-deep[v];
       for(int i=0;(1<<i)<=k;i++)
       {
           if((1<<i)&k)
            u=p[u][i];
       }
       if(u==v)
        return u;
        int N=log2((double)n);
       for(int i=N;i>=0;i--)
       {
           if(p[u][i]!=p[v][i])
           {
               u=p[u][i],
               v=p[v][i];
           }
       }
       return p[u][0];
    }
    int main()
    {
        while(~scanf("%d",&n)){
           init();
          int u,v;
       for(int i=1;i<n;i++)
       {
          scanf("%d %d",&u,&v);
          add_edge(u,v);
          add_edge(v,u);
       }
       dfs(1);
       st_init();
       int Q;
       scanf("%d",&Q);
       lca_init();
       while(Q--)
       {
           int l,r;
           scanf("%d %d",&l,&r);
           l--,r--;
           int id_max=st_q_max(l,r)+1;
           int id_min=st_q_min(l,r)+1;
           printf("%d
    ",lca(id_max,id_min));
       }
      }
    }
    View Code
  • 相关阅读:
    学习vue_01
    练习题 vue_01:
    测试
    django小结
    BBS_02day
    BBS 03day
    力扣(LeetCode)412. Fizz Buzz
    力扣(LeetCode)415. 字符串相加
    力扣(LeetCode)448. 找到所有数组中消失的数字
    力扣(LeetCode)453. 最小移动次数使数组元素相等
  • 原文地址:https://www.cnblogs.com/linhaitai/p/10035452.html
Copyright © 2020-2023  润新知