• SPOJ 1487. Query on a tree III


    SPOJ Problem Set (classical)

    SPOJ 1487. Query on a tree III

    Problem code: PT07J

     

     

    You are given a node-labeled rooted tree with n nodes.

    Define the query (xk): Find the node whose label is k-th largest in the subtree of the node x. Assume no two nodes have the same labels.

    Input

    The first line contains one integer n (1 <= n <= 105). The next line contains n integers li (0 <= li <= 109) which denotes the label of the i-th node.

    Each line of the following n - 1 lines contains two integers uv. They denote there is an edge between node u and node v. Node 1 is the root of the tree.

    The next line contains one integer m (1 <= m <= 104) which denotes the number of the queries. Each line of the nextm contains two integers xk. (k <= the total node number in the subtree of x)

    Output

    For each query (xk), output the index of the node whose label is the k-th largest in the subtree of the node x.

    Example

    Input:
    5
    1 3 5 2 7
    1 2
    2 3
    1 4
    3 5
    4
    2 3
    4 1
    3 2
    3 2
    
    Output:
    5
    4
    5
    5
    ---------------------------------------------------------------
    题目大意:询问树上某棵子树上第K大的节点。
    解题思路:用一次dfs把树搞成括号序列,记录每个节点的开始和结束时间戳,然后就变成了区间第k大值,用划分树模板即可。
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <map>
    #define MID(x,y) ( ( x + y ) >> 1 )
    #define L(x) ( x << 1 )
    #define R(x) ( x << 1 | 1 )
    #define BUG puts("here!!!")
    #define LL long long
    using namespace std;
    
    const int N=100005;
    int n,m;
    int val[40][N],sorted[N],toleft[40][N];
    bool cmp(int a,int b)
    {
        return a<b;
    }
    struct node
    {
        int l,r;
        int getmid()
        {
            return (l+r)>>1;
        }
    } tree[N * 4];
    void build(int rt,int l,int r,int d)
    {
        tree[rt].l=l;
        tree[rt].r=r;
        if(l==r) return;
        int mid=(l+r) >> 1;
        int same=mid-l+1;
        for(int i=l; i<=r; ++i)
            if (val[d][i]<sorted[mid])same--;
        int lpos=l;
        int rpos=mid+1;
        for(int i=l; i<=r; ++i)
        {
            if(i==l)toleft[d][i]=0;
            else toleft[d][i]=toleft[d][i - 1];
            if(val[d][i]<sorted[mid])
            {
                toleft[d][i]++;
                val[d+1][lpos++]=val[d][i];
            }
            else if(val[d][i]>sorted[mid])val[d+1][rpos++]=val[d][i];
            else if(same)
            {
                same--;
                toleft[d][i]++;
                val[d+1][lpos++]=val[d][i];
            }
            else val[d+1][rpos++]=val[d][i];
        }
        build(L(rt),l,mid,d+1);
        build(R(rt),mid+1,r,d+1);
    }
    int query(int rt, int l, int r, int d, int k)
    {
        if(l==r)return val[d][l];
        int s,ss;
        if(l==tree[rt].l)
        {
            s=toleft[d][r];
            ss=0;
        }
        else
        {
            s=toleft[d][r]-toleft[d][l-1];
            ss=toleft[d][l-1];
        }
        if(k<=s)
        {
            int left=tree[rt].l+ss;
            int right=left+s-1;
            return query(L(rt),left,right,d+1,k);
        }
        else
        {
            int b=l-tree[rt].l-ss;
            int left=tree[rt].getmid()+b+1;
            int right=left+r-l-s;
            return query(R(rt),left,right,d+1,k-s);
        }
    }
    
    int lab[N],one[N],two[N],eid,num;
    int head[N],ed[N<<1],nxt[N<<1];
    map<int,int>ha;
    
    void addedge(int s,int e)
    {
        ed[eid]=e;
        nxt[eid]=head[s];
        head[s]=eid++;
    }
    
    void dfs(int s,int f)
    {
        one[s]=num;
        sorted[num]=lab[s];
        val[0][num++]=lab[s];
        for(int i=head[s]; ~i; i=nxt[i])
            if(ed[i]!=f)dfs(ed[i],s);
        two[s]=num-1;
    }
    
    int main()
    {
    //    freopen("/home/axorb/in","r",stdin);
        ha.clear();
        scanf("%d",&n);
        eid=0;
        memset(head,-1,sizeof(head));
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&lab[i]);
            ha[lab[i]]=i;
        }
        for(int i=1; i<n; i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            addedge(a,b);
            addedge(b,a);
        }
        num=0;
        dfs(1,-1);
    sort(sorted,sorted+n,cmp);
    build(1,0,n-1,0);
        int q;
        scanf("%d",&q);
        while(q--)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            printf("%d\n",ha[query(1,one[a],two[a],0,b)]);
        }
    }
    

      

    也许有挫折,但这些,怎能挡住湘北前进的步伐
  • 相关阅读:
    ping 网关不同的原因(51cto博客搬迁)
    Linux Shell常用命令总结(51cto 博客搬迁)
    学生管理系统管理系统
    offset属性在各版本浏览器中的不同算法
    常用正则表达式
    select城市3级联动
    html5表单验证消息框
    清除浏览器默认选择效果
    排序之简单的冒泡排序
    简单的桶排序
  • 原文地址:https://www.cnblogs.com/Fatedayt/p/2585664.html
Copyright © 2020-2023  润新知