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)]);

    }

}

  

你可能感兴趣的:(query)