zoukankan      html  css  js  c++  java
  • hdu 5266 pog loves szh III(lca + 线段树)

    I - pog loves szh III
    Time Limit:6000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u

    Description

    Pog and Szh are playing games. Firstly Pog draw a tree on the paper. Here we define 1 as the root of the tree.Then Szh choose some nodes from the tree. He wants Pog helps to find the least common ancestor (LCA) of these node.The question is too difficult for Pog.So he decided to simplify the problems.The nodes picked are consecutive numbers from l_i to r_i ([l_i, r_i])

    Hint : You should be careful about stack overflow !

    Input

    Several groups of data (no more than 3 groups,n geq 10000 or Q geq 10000). 

    The following line contains ans integers,n (2 leq n leq 300000)

    AT The following n-1 line, two integers are b_i and c_i at every line, it shows an edge connecting b_i and c_i

    The following line contains ans integers,Q (Q leq 300000)

    AT The following Q line contains two integers li and ri(1 leq li leq ri leq n).

    Output

    For each case,output Q integers means the LCA of [l_i,r_i].

    Sample Input

    5
    1 2
    1 3
    3 4
    4 5
    5
    1 2
    2 3
    3 4
    3 5
    1 5

    Sample Output

    1
    1
    3
    3
    1

    /*
    hdu 5266 pog loves szh III(lca + 线段树)
    
    problem:
    给你一棵树,然后查询节点l~r的最小公共祖先
    
    solve:
    如果用在线算法,查询的时候可以直接O(1)实现,然后查询节点l~r的最小公共祖先感觉很像区间最值
    而且可以发现 如果知道a~b和c~d的最小公共祖先,那么a~d的lca 就是a~b的lca和c~d的lca的最小公共祖先
    所以考虑用线段树解决查询问题
    
    hhh-2016-08-08 16:58:09
    */
    #pragma comment(linker,"/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    #include <map>
    #include <queue>
    #include <vector>
    #include <set>
    #define lson (i<<1)
    #define rson ((i<<1)|1)
    using namespace std;
    typedef long long ll;
    const int maxn=300000 + 500;
    const int INF=0x3f3f3f3f;
    const int mod = 1e9+7;
    int n,tot,cnt;
    int head[maxn],rmq[maxn];
    int flag[maxn];
    int vis[maxn];
    int P[maxn];
    int F[maxn<<1];
    
    struct Edge
    {
        int from,to,next;
    } edge[maxn << 1];
    
    int fin(int x)
    {
        if(F[x] == -1) return x;
        return F[x] = fin(F[x]);
    }
    
    void unio(int a,int b)
    {
        int ta=  fin(a);
        int tb= fin(b);
        if(ta != tb)
            F[ta] = tb;
    }
    
    void add_edge(int u,int v)
    {
        edge[tot].from = u,edge[tot].to = v,edge[tot].next=head[u],head[u] = tot++;
    }
    
    struct ST
    {
        int m[maxn << 1];
        int dp[maxn << 1][20];
        void ini(int n)
        {
            m[0] = -1;
            for(int i = 1; i <= n; i++)
            {
                m[i] = ((i&(i-1)) == 0)? m[i-1]+1:m[i-1];
                dp[i][0] = i;
            }
            for(int j = 1; j <= m[n]; j++)
            {
                for(int i = 1; i+(1<<j)-1 <= n; i++)
                    dp[i][j] = rmq[dp[i][j-1]] < rmq[dp[i+(1<<(j-1))][j-1]] ?
                               dp[i][j-1] : dp[i+(1 << (j-1))][j-1];
            }
        }
        int query(int a,int b)
        {
            if(a > b)
                swap(a,b);
            int k = m[b-a+1];
            return rmq[dp[a][k]] <= rmq[dp[b-(1<<k)+1][k]] ?
                   dp[a][k]:dp[b-(1<<k)+1][k];
        }
    };
    
    ST st;
    
    void dfs(int u,int pre,int dep)
    {
        F[++cnt] = u;
        rmq[cnt] = dep;
        P[u] = cnt;
    
        for(int i = head[u]; ~i; i = edge[i].next)
        {
            int v = edge[i].to;
            if(v == pre)
                continue;
            dfs(v,u,dep+1);
            F[++cnt] = u;
            rmq[cnt] = dep;
        }
    }
    
    int query_lca(int a,int b)
    {
        return F[st.query(P[a],P[b])];
    }
    void ini()
    {
        memset(flag,0,sizeof(flag));
        memset(head,-1,sizeof(head));
        tot =0;
        cnt = 0;
    }
    
    struct node
    {
        int l,r;
        int lca;
        int mid()
        {
            return (l+r)>>1;
        }
    } tree[maxn << 2];
    
    void push_up(int i)
    {
        tree[i].lca = query_lca(tree[lson].lca,tree[rson].lca);
    //    cout << tree[lson].lca << " " <<tree[rson].lca <<endl;
    //    cout << tree[i].l<< " " << tree[i].r << " "  <<tree[i].lca <<endl;
    }
    
    void build(int i,int l,int r)
    {
        tree[i].l = l,tree[i].r = r;
        if(l == r)
        {
            tree[i].lca = l;
    //        cout << tree[i].l<< " " << tree[i].r << " "  <<tree[i].lca <<endl;
            return ;
        }
        int mid = tree[i].mid();
        build(lson,l,mid);
        build(rson,mid+1,r);
        push_up(i);
    }
    
    int query(int i,int l,int r)
    {
        if(tree[i].l >= l && tree[i].r <= r)
        {
            return tree[i].lca;
        }
        int mid = tree[i].mid();
        if(r <= mid)
            return query(lson,l,r);
        else if(l > mid)
            return query(rson,l,r);
        else
            return query_lca(query(lson,l,mid),query(rson,mid+1,r));
        push_up(i);
    }
    
    int main()
    {
        int n,m,k;
        int a,b,c;
      //  freopen("in.txt","r",stdin);
        while(scanf("%d",&n) != EOF)
        {
            ini();
    
            for(int i = 1; i < n; i++)
            {
                scanf("%d%d",&a,&b);
                add_edge(b,a);
                add_edge(a,b);
                flag[b] = 1;
            }
            dfs(1,1,0);
            st.ini(2*n-1);
            scanf("%d",&m);
            build(1,1,n);
           // printf("1 2 %d
    ",query_lca(1,2));
            for(int i = 1; i <= m; i++)
            {
                scanf("%d%d",&a,&b);
                printf("%d
    ",query(1,a,b));
    //printf("%d
    ",query_lca(a,b));
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    tp3中子查询 逻辑条件是or
    数据量大的情况用布隆过滤器判断是否已存在
    pip 通过pqi切换源到国内镜像
    php先响应后处理
    selenium登录网银,密码控件输入
    mysql 查询a表在b表中不存在的记录
    下列java代码中的变量a、b、c分别在内存的______存储区存放。
    关于选中的磁盘具有MBR分区表。在EFI系统上,Windows只能安装到GPT磁盘。问题解决
    VBOX不能为虚拟电脑打开一个新任务解决方法
    解决虚拟机似乎正在使用的问题
  • 原文地址:https://www.cnblogs.com/Przz/p/5757303.html
Copyright © 2011-2022 走看看