主席树模板(查询区间第K大的元素)

/****************************
* Author : W.A.R            *
* Date : 2020-08-07-17:13   *
****************************/
/*
主席树多组样例一定要记得初始化sz=0!!!!!!!!!!
*/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=1e5+50;
const ll mod=1e9+7;
namespace Fast_IO{ //orz laofu
    const int MAXL((1 << 18) + 1);int iof, iotp;
    char ioif[MAXL], *ioiS, *ioiT, ioof[MAXL],*iooS=ioof,*iooT=ioof+MAXL-1,ioc,iost[55];
    char Getchar(){
        if (ioiS == ioiT){
            ioiS=ioif;ioiT=ioiS+fread(ioif,1,MAXL,stdin);return (ioiS == ioiT ? EOF : *ioiS++);
        }else return (*ioiS++);
    }
    void Write(){fwrite(ioof,1,iooS-ioof,stdout);iooS=ioof;}
    void Putchar(char x){*iooS++ = x;if (iooS == iooT)Write();}
    inline int read(){
        int x=0;for(iof=1,ioc=Getchar();(ioc<'0'||ioc>'9')&&ioc!=EOF;)iof=ioc=='-'?-1:1,ioc=Getchar();
        if(ioc==EOF)exit(0);
        for(x=0;ioc<='9'&&ioc>='0';ioc=Getchar())x=(x<<3)+(x<<1)+(ioc^48);return x*iof;
    }
    inline long long read_ll(){
        long long x=0;for(iof=1,ioc=Getchar();(ioc<'0'||ioc>'9')&&ioc!=EOF;)iof=ioc=='-'?-1:1,ioc=Getchar();
        if(ioc==EOF)exit(0);
        for(x=0;ioc<='9'&&ioc>='0';ioc=Getchar())x=(x<<3)+(x<<1)+(ioc^48);return x*iof;
    }
    template <class Int>void Print(Int x, char ch = ''){
        if(!x)Putchar('0');if(x<0)Putchar('-'),x=-x;while(x)iost[++iotp]=x%10+'0',x/=10;
        while(iotp)Putchar(iost[iotp--]);if (ch)Putchar(ch);
    }
    void Getstr(char *s, int &l){
        for(ioc=Getchar();ioc==' '||ioc=='
'||ioc=='	';)ioc=Getchar();
        if(ioc==EOF)exit(0);
        for(l=0;!(ioc==' '||ioc=='
'||ioc=='	'||ioc==EOF);ioc=Getchar())s[l++]=ioc;s[l] = 0;
    }
    void Putstr(const char *s){for(int i=0,n=strlen(s);i<n;++i)Putchar(s[i]);}
} // namespace Fast_IO 
using namespace Fast_IO;
struct node
{
    int l,r,v;
}tree[maxn*20];
int rt[maxn],sz=0;
int a[maxn],b[maxn];
void build(int &rt,int l,int r){
    rt=++sz;tree[rt].v=0;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(tree[rt].l,l,mid);build(tree[rt].r,mid+1,r);
}
int update(int o,int l,int r,int pos){
    int oo=++sz;tree[oo]=tree[o];tree[oo].v++;
    if(l==r)return oo;
    int mid=(l+r)>>1;
    if(mid>=pos)tree[oo].l=update(tree[oo].l,l,mid,pos);else tree[oo].r=update(tree[oo].r,mid+1,r,pos);
    return oo;
}
int query(int x,int y,int l,int r,int pos){
    if(l==r)return l;
    int mid=(l+r)>>1;int sum=tree[tree[y].l].v-tree[tree[x].l].v;
    if(sum>=pos)return query(tree[x].l,tree[y].l,l,mid,pos);else return query(tree[x].r,tree[y].r,mid+1,r,pos-sum);
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n,m;
        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;
        sz=0;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],1,q,p);
        }
        while(m--){
            int l,r,x;scanf("%d%d%d",&l,&r,&x);
            printf("%d
",b[query(rt[l-1],rt[r],1,q,x)]);
        }
    }
}
原文地址:https://www.cnblogs.com/wuanran/p/13454048.html