[Hdu] 2665 Kth number(主席树模板题)

题目链接:Hdu 2665

这道题也放上来,同样是主席树模板,不过是求区间第K大的,基本和上个链接的是一样的,就是怕有人不明白(比如自己)。如果想看主席树模版有解释的可以去[Hdu] 4417 Super Mario (主席树模板题)看看。

同样此题数据的原因要离散(好像这类权值线段树之类的都要离散)。

代码:

#include
#include
#include
#include
using namespace std;
#define ll long long
#define N 100005
inline int read(){
    int x = 0,f = 1;char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9'){ x = x*10+ch-'0'; ch = getchar(); }
    return x*f;
}

int root[N],cnt;
struct node{
    int lson,rson,sum;
}t[N<<5];
int a[N],d[N],tot;

int erfen(int x){
    int l = 1,r = tot;
    int mid;
    while(l <= r){
        mid = (l+r)>>1;
        if(d[mid] > x) r = mid-1;
        else l = mid+1;
    }
    return r;
}

void build(int &root,int l,int r){
    root = ++cnt;
    t[root].sum = 0;
    if(l == r) return;
    int mid = (l+r)>>1;
    build(t[root].lson,l,mid);
    build(t[root].rson,mid+1,r);
}

void add(int &root1,int root2,int l,int r,int x){
    root1 = ++cnt;
    t[root1] = t[root2];
    t[root1].sum++;
    if(l == r) return;
    int mid = (l+r)>>1;
    if(mid < x) add(t[root1].rson,t[root2].rson,mid+1,r,x);
    else add(t[root1].lson,t[root2].lson,l,mid,x);
}

int query(int p,int q,int l,int r,int x){
    if(l == r) return l;
    int mid = (l+r)>>1;
    int ans = t[t[q].lson].sum-t[t[p].lson].sum;
    if(ans < x) return query(t[p].rson,t[q].rson,mid+1,r,x-ans);
    else return query(t[p].lson,t[q].lson,l,mid,x);
}

int main(){
    int T = read();
    for(int t = 1;t <= T;t++){
        int n = read(),m = read();
        cnt = 0; tot = 1;
        for(int i = 1;i <= n;i++)
            d[i] = a[i] = read();
        sort(d+1,d+n+1);
        for(int i = 2;i <= n;i++)
            if(d[i] != d[i-1])
                d[++tot] = d[i];
        for(int i = 1;i <= n;i++)
            a[i] = erfen(a[i]);
        build(root[0],1,tot);
        for(int i = 1;i <= n;i++)
            add(root[i],root[i-1],1,tot,a[i]);
        while(m--){
            int l = read(),r = read(),x = read();
            printf("%d\n",d[query(root[l-1],root[r],1,tot,x)]);
        }
    }
    return 0;
}

你可能感兴趣的:(hdu题解,可持久化线段树,主席树)