主席树

静态主席树

#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
const int MAXN=10;
int n,m,a[MAXN],b[MAXN],N;
//a为原数组,b为离散后的数组,N为离散后的个数
int root[MAXN],sum[MAXN<<5],node_num;
//root[i]:插入i个节点后的树的编号
//sum[i]:节点i代表的区间内数字出现的次数
int lson[MAXN<<5],rson[MAXN<<5];
//lson[i]:编号为i的节点的左儿子编号
int build(int l,int r){
    int num=++node_num;
    if(l^r){
        lson[num]=build(l,mid);
        rson[num]=build(mid+1,r);
    }
    return num;
}
int update(int pre,int l,int r,int v){
    int num=++node_num;
    lson[num]=lson[pre];
    rson[num]=rson[pre];
    sum[num]=sum[pre]+1;
    if(l^r){
        if(v<=mid)lson[num]=update(lson[pre],l,mid,v);
        else rson[num]=update(rson[pre],mid+1,r,v);
    }
    return num;
}
int query(int x,int y,int l,int r,int k){
    if(l==r)return b[l];
    int num=sum[lson[y]]-sum[lson[x]];
    if(k<=num)return query(lson[x],lson[y],l,mid,k);
    else return query(rson[x],rson[y],mid+1,r,k-num);
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i){scanf("%d",a+i);b[i]=a[i];}
    sort(b+1,b+n+1);
    N=unique(b+1,b+1+n)-b-1;
    root[0]=build(1,N);
    for(int i=1;i<=n;++i){
        int v=lower_bound(b+1,b+1+N,a[i])-b;
        root[i]=update(root[i-1],1,N,v);
    }
    int x,y,k;
    while(m--){
        scanf("%d%d%d",&x,&y,&k);
        printf("%d
",query(root[x-1],root[y],1,N,k));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/foursmonth/p/14161826.html