HDU-2665 Kth number (静态主席树+离散化)

Kth number 

Give you a sequence and ask you the kth big number of a inteval.

Input

The first line is the number of the test cases. 
For each test case, the first line contain two integer n and m (n, m <= 100000), indicates the number of integers in the sequence and the number of the quaere. 
The second line contains n integers, describe the sequence. 
Each of following m lines contains three integers s, t, k. 
[s, t] indicates the interval and k indicates the kth big number in interval [s, t]

Output

For each test case, output m lines. Each line contains the kth big number.

Sample Input

1 
10 1 
1 4 2 3 5 6 7 8 9 0 
1 3 2 

Sample Output

2

题目大意:t组输入,n,m,给出一个长度为n的数列,有m个查询,查询[l,r] 间第k个数。

思路:主席树模板题,具体思路是因为数据较大先对数组去重离散化,对离散后的数据1-q建一棵线段树作为基础主席树,然后对原数组每一个区间[ 1 , i ] 统计各数字的个数建立新的线段树,但是因为对于每一个区间相较于前一个区间值增加了一个数,如果重新建一棵新的线段树会很浪费空间,所以只需要插入新的不一样的节点即可。主席树建好后就是查询,查询区间 [l,r] 的第k个数,可以利用[1,r] 与 [1,l-1]区间的个数差,如果左子区间的个数 x>=k 就在其左子区间找第k个数,如果 x

#include
#include
#include
#include
using namespace std;
const int N=100005;
int a[N],b[N],tot;
int rt[N],ls[N<<5],rs[N<<5],sum[N<<5];

void build(int &t,int l,int r) //建基础主席树
{
    t=++tot;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(ls[t],l,mid);
    build(rs[t],mid+1,r);
}
int update(int t,int x,int l,int r) //插入新节点
{
    int nt=++tot;
    ls[nt]=ls[t];
    rs[nt]=rs[t];
    sum[nt]=sum[t]+1; 
    if(l==r) return nt;
    int mid=(l+r)>>1;
    if(x<=mid) ls[nt]=update(ls[nt],x,l,mid);
    else rs[nt]=update(rs[nt],x,mid+1,r);
    return nt;
}
int query(int u,int v,int l,int r,int k) //查询
{
    int x=sum[ls[v]]-sum[ls[u]],ans;
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(x>=k) ans=query(ls[u],ls[v],l,mid,k);
    else ans=query(rs[u],rs[v],mid+1,r,k-x);
    return ans;
}

int main()
{
    int t,n,m;
    scanf("%d",&t);
    while(t--)
    {
        tot=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        sort(b+1,b+1+n);
        int q=unique(b+1,b+1+n)-(b+1);
        build(rt[0],1,q);
        for(int i=1;i<=n;i++)
        {
            int p=lower_bound(b+1,b+1+q,a[i])-b;
            rt[i]=update(rt[i-1],p,1,q);
        }
        while(m--)
        {
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            int ans=query(rt[l-1],rt[r],1,q,k);
            printf("%d\n",b[ans]);
        }
    }
    return 0;
}

 

主席树

你可能感兴趣的:(主席树)