POJ 2104 K-th Number(主席树)

Description
给出一个长度为n的序列a,给出m次查询,每次查询区间[l,r]中第k大的数是什么
Input
第一行两个整数n和m分别表示序列长度和查询次数,第二行n个整数表示序列a,之后m行每行三个整数l,r和k表示一次查询
Output
对于每次查询,输出区间[l,r]中第k大的数
Sample Input
7 3
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3
Sample Output
5
6
3
Solution
主席树静态区间第k大,模版题~
Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 111111
struct Tree
{
    int left,right,data;
    Tree(){left=right=data=0;}
}T[22*maxn];
int n,m,l,r,k,a[maxn],pos[maxn],id[maxn],root[maxn],cnt;
int cmp(int x,int y)
{
    return a[x]<a[y];
}
void insert(int &i,int l,int r,int x)
{
    T[++cnt]=T[i];
    i=cnt;
    T[i].data++;
    if(l==r) return ;
    int mid=(l+r)>>1;
    if(x<=mid) insert(T[i].left,l,mid,x);
    else insert(T[i].right,mid+1,r,x);
}
int query(int i,int j,int l,int r,int k)
{
    if(l==r) return l;
    int temp=T[T[j].left].data-T[T[i].left].data,mid=(l+r)>>1;
    if(k<=temp) query(T[i].left,T[j].left,l,mid,k);
    else query(T[i].right,T[j].right,mid+1,r,k-temp);
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            pos[i]=i;
        }
        sort(pos+1,pos+n+1,cmp);
        for(int i=1;i<=n;i++)
            id[pos[i]]=i;
        cnt=root[0]=0;
        for(int i=1;i<=n;i++)
        {
            root[i]=root[i-1];
            insert(root[i],1,n,id[i]);
        }
        while(m--)
        {
            scanf("%d%d%d",&l,&r,&k);
            int ans=query(root[l-1],root[r],1,n,k);
            printf("%d\n",a[pos[ans]]);
        }
    }
    return 0;
}

你可能感兴趣的:(POJ 2104 K-th Number(主席树))