[模板]主席树


求区间第K小:

#include
#include
#include<string>
#include
#define WR WinterRain
using namespace std;
const int WR=1001000;
struct ChairMan{
    int lson,rson,val;//记录左儿子右儿子,还有一个大小
    ChairMan(){val=0;}//为了节约空间最好别用l,r
    //毕竟有丧心病狂的O(nlogn)空间……
}tree[WR<<4];//空间开大
int n,m,un;
int a[WR],b[WR];
int root[WR],tot;
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<3)+(s<<1)+ch-48;
        ch=getchar();
    }
    return s*w;
}
void pushup(int k){//这里相应的要改一下
    tree[k].val=tree[tree[k].lson].val+tree[tree[k].rson].val;
}
void cpy(int x,int y){
    tree[x].lson=tree[y].lson,tree[x].rson=tree[y].rson;
    tree[x].val=tree[y].val;
}
void build(int &k,int l,int r){//动态开点建树
    if(!k) k=++tot;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(tree[k].lson,l,mid);
    build(tree[k].rson,mid+1,r);
}
void insrt(int &k,int l,int r,int pos,int v){
    if(!k) k=++tot;
    cpy(k,pos);
    if(l==r){
        tree[k].val++;
        return;
    }
    int mid=(l+r)>>1;//权值线段树式的修改
    if(v<=mid) tree[k].lson=0,insrt(tree[k].lson,l,mid,tree[pos].lson,v);
    else tree[k].rson=0,insrt(tree[k].rson,mid+1,r,tree[pos].rson,v);
    pushup(k);
}
int query(int k,int l,int r,int pos,int v){
    if(l==r) return l;
    int tmp=tree[tree[k].lson].val-tree[tree[pos].lson].val;
    int mid=(l+r)>>1;
    if(v<=tmp) return query(tree[k].lson,l,mid,tree[pos].lson,v);
    else return query(tree[k].rson,mid+1,r,tree[pos].rson,v-tmp);
    //这里有一点点小差分,如果当前第k大在左子树里,直接查左子树
    //如果在右子树里,剪掉左子树大小再查询
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) a[i]=b[i]=read();
    sort(b+1,b+1+n);
    un=unique(b+1,b+1+n)-b-1;//必备离散化
    build(root[0],1,un);//先建出权值线段树再说插入的事
    for(int i=1;i<=n;i++){
        a[i]=lower_bound(b+1,b+un+1,a[i])-b;
        //printf("a[i]=%d\n",a[i]);
        insrt(root[i],1,un,root[i-1],a[i]);
    }
    for(int i=1;i<=m;i++){
        int x=read(),y=read(),k=read();
        printf("%d\n",b[query(root[y],1,un,root[x-1],k)]);
    }
    return 0;
}