HDU2665 Kth number(归并树模板)

Kth number

传送门1
传送门2
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 n and m(n,m<=100000) m ( n , m <= 100000 ) , indicates the number of integers in the sequence and the number of the quaere.
The second line contains n n integers, describe the sequence.
Each of following m m lines contains three integers s,t,k s , t , k .
[s,t] [ s , t ] indicates the interval and k k indicates the kth big number in interval [s,t] [ s , t ]

Output

For each test case, output m 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大数.

分析

线段树(归并树)+ 二分答案.
HDU2665 Kth number(归并树模板)_第1张图片
从下往上构造整棵树,每一个节点为左右儿子节点的归并.
然后对 [l,r] [ l , r ] 中大于等于 x x 的数进行二分.

CODE

#include
#include
#include
#include
#include
#define N 100005
#define Lson l,mid,p<<1
#define Rson mid+1,r,p<<1|1
#define FOR(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int A[N],B[N];
struct SegT {
    int l,r;
    vector<int> num;
} tree[N<<2];

void build(int l,int r,int p) {
    tree[p].l=l;tree[p].r=r;
    tree[p].num.clear();
    tree[p].num.resize(0);
    if(l==r) {
        tree[p].num.push_back(A[l]);
        return;
    }
    int mid=(l+r)>>1;build(Lson);build(Rson);
    tree[p].num.resize(tree[p<<1].num.size()+tree[p<<1|1].num.size());
    merge(tree[p<<1].num.begin(),tree[p<<1].num.end(),tree[p<<1|1].num.begin(),tree[p<<1|1].num.end(),tree[p].num.begin());
    return;
}
int query(int l,int r,int p,int x) {
    if(tree[p].l==l&&tree[p].r==r) return upper_bound(tree[p].num.begin(),tree[p].num.end(),x)-tree[p].num.begin();
    int mid=(tree[p].l+tree[p].r)>>1;
    if(r<=mid) return query(l,r,p<<1,x);
    else if(l>=mid+1) return query(l,r,p<<1|1,x);
    else return query(l,mid,p<<1,x)+query(mid+1,r,p<<1|1,x);
}

int main() {
    int T,n,m,s,t,k;
    scanf("%d",&T);
    while(T--) {
        scanf("%d %d",&n,&m);
        FOR(i,1,n) {
            scanf("%d",&A[i]);
            B[i]=A[i];
        }
        sort(B+1,B+n+1);
        int LL=1,RR=unique(B+1,B+n+1)-B-1;
        build(1,n,1);
        FOR(i,1,m) {
            int l=LL,r=RR;
            scanf("%d %d %d",&s,&t,&k);
            while(lint mid=(l+r)>>1;
                if(query(s,t,1,B[mid])>=k)r=mid;
                else l=mid+1;
            }
            printf("%d\n",B[l]);
        }
    }
    return 0;
}

你可能感兴趣的:(数据结构,----线段树)