主席树

/*

 主席树做法,查询区间第K大,输入的l,r是从0开始

 区间第K大解法:https://www.cnblogs.com/GoldenFingers/p/9475172.html

 */

#include <iostream>

#include <stdio.h>

#include <string.h>

#include <stack>

#include <map>

#include <vector>

#include <algorithm>

using namespace std;

typedef long long ll;

const int maxn=5e4+10;

vector<int>v;

int rt[maxn*20],ls[maxn*20],rs[maxn*20],sum[maxn*20];

int tot,sz;

int a[maxn],b[maxn];

void build(int &root,int l,int r){

    root = ++tot;

    sum[root]=0;

    if(l==r)return ;

    int mid=(l+r)/2;

    build(ls[root],l,mid);

    build(rs[root],mid+1,r);

}

void update(int &root,int l,int r,int last,int p){

    root=++tot;

    ls[root]=ls[last];

    rs[root]=rs[last];

    sum[root]=sum[last]+1;

    if(l==r)return ;

    int mid=(l+r)/2;

    if(p<=mid)update(ls[root],l,mid,ls[last],p);

    else update(rs[root],mid+1,r,rs[last],p);

}

void init(int n){

    for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];

    sort(b+1,b+1+n);

    sz=(int)(unique(b+1, b+1+n)-(b+1));

    tot=0;

    build(rt[0],1,sz);

    for(int i=1;i<=n;i++){

        int pos=(int)(lower_bound(b+1, b+1+sz, a[i])- b);

        update(rt[i],1,sz,rt[i-1],pos);

    }

}

int query(int ql,int qr,int l,int r,int k){

    if(l==r)return l;

    int mid=(l+r)/2;

    int cnt=sum[ls[qr]]-sum[ls[ql]];

    if(k<=cnt)return query(ls[ql],ls[qr],l,mid,k);

    else return query(rs[ql],rs[qr],mid+1,r,k-cnt);

}

int main(){

    int n,q;

    scanf("%d",&n);

    init(n);

    scanf("%d",&q);

    while(q--){

        int l,r,k;

        scanf("%d%d%d",&l,&r,&k);

        l++; r++;

        int id=query(rt[l-1],rt[r],1,sz,r-l+1-k+1);

        printf("%d\n",b[id]);

    }

    return 0;

}

地址:https://www.cnblogs.com/zyf0163/p/4749042.html

posted @ 2019-04-21 18:28  ljy3268  阅读(104)  评论(0编辑  收藏  举报