HDU

来源:互联网 发布:我的世界js编辑器jside 编辑:程序博客网 时间:2024/06/03 18:11

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



解题思路:不多解释了,可持久化线段树解决静态区间第K大。推荐这篇博客 http://blog.csdn.net/farestorm/article/details/50337527  看完就懂啦~!




#include<iostream>#include<algorithm>#include<stdlib.h>#include<memory.h>#include<queue>using namespace std;const int MAXN=100101;int ls[MAXN*20];//记录左儿子int rs[MAXN*20];//记录右儿子int sum[MAXN*20];//记录区间中包含数的个数int num[MAXN];//原数组int sorted[MAXN];//排序并去重后的数组int T[MAXN];//记录第i次操作的根节点(可持久化线段树)int n,m,tot=0;//动态开点//建立一棵空树,初始状态为一棵空树void build(int l,int r,int &x){    x=++tot;    sum[x]=0;    if(l==r)        return;    int m=(l+r)/2;    build(l,m,ls[x]);    build(m+1,r,rs[x]);}//单点更新void update(int last,int p,int l,int r,int &x){    x=++tot;    ls[x]=ls[last];    rs[x]=rs[last];    sum[x]=sum[last]+1;    if(l==r)        return;    int m=(l+r)/2;    if(p<=m)        update(ls[last],p,l,m,ls[x]);    else        update(rs[last],p,m+1,r,rs[x]);}int query(int s,int t,int l,int r,int k){    if(l==r)        return l;    int m=(l+r)/2;    int cnt=sum[ls[t]]-sum[ls[s]];    if(k<=cnt)        return query(ls[s],ls[t],l,m,k);    return query(rs[s],rs[t],m+1,r,k-cnt);}int main(){        int t;    scanf("%d",&t);        while(t--){                tot=0;                int x,y,z;        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++){            scanf("%d",&sorted[i]);            num[i]=sorted[i];        }                sort(sorted+1,sorted+n+1);                int cnt=unique(sorted+1,sorted+n+1)-sorted-1;        build(1,cnt,T[0]);                for(int i=1;i<=n;i++)            num[i]=lower_bound(sorted+1,sorted+cnt+1,num[i])-sorted;//把原数组修改为在排序过后的数组的下标                //因为线段树存的值是数字出现的个数        for(int i=1;i<=n;i++)            update(T[i-1],num[i],1,cnt,T[i]);                for(int i=1;i<=m;i++){            scanf("%d%d%d",&x,&y,&z);            printf("%d\n",sorted[query(T[x-1],T[y],1,cnt,z)]);        }    }        return 0;}




原创粉丝点击