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;
    }
    

      

  • 相关阅读:
    【leetcode】反转字符串
    【leetcode】反转字符串 II
    053-669
    053-668
    053-667
    053-666
    053-665
    053-664
    053-663
    053-662
  • 原文地址:https://www.cnblogs.com/Przz/p/5757303.html
Copyright © 2011-2022 走看看