以很小的空间相当于建立了n棵线段树,进行查询区间第k小
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn= 2e5 + 100;
struct hyq{
int l,r,sum;
}T[maxn*40];
int a[maxn], b[maxn],A[maxn];
int root[maxn];
int n,q,cnt;
void ins(int &u,int l,int r,int p){
T[++cnt]=T[u];
u=cnt;
if(l==r){
T[u].sum++;
return;
}
int mid=(l+r)/2;
if(p<=mid) ins(T[u].l,l,mid,p);
else ins(T[u].r,mid+1,r,p);
T[u].sum=T[T[u].l].sum+T[T[u].r].sum;
}
int query(int lt,int rt,int l,int r,int k){
if(l==r) return l;
int mid=(l+r)/2;
int t=T[T[rt].l].sum-T[T[lt].l].sum;
if(k<=t) return query(T[lt].l,T[rt].l,l,mid,k);
else return query(T[lt].r,T[rt].r,mid+1,r,k-t);
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
A[i]=a[i];
}
sort(A+1,A+n+1);
A[0]=unique(A+1,A+n+1)-A-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(A+1,A+A[0]+1,a[i])-A;
}
root[0]=0;
for(int i=1;i<=n;i++){
root[i]=root[i-1];
ins(root[i],1,A[0],a[i]);
}
for(int i=1;i<=q;i++){
int ll,rr,kk;
scanf("%d%d%d",&ll,&rr,&kk);
cout<<A[query(root[ll-1],root[rr],1,A[0],kk)]<<endl;
}
}
访问历史版本的主席树
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1001010;
struct node{
int l,r,sum;
}T[maxn*30];
int read(){
char c=getchar();
int x=0,f=1;
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int n,m,cnt;
int A[maxn],a[maxn],root[maxn];
void build(int &u,int l,int r){
u=++cnt;
if(l==r){
T[u].sum=a[l];
return;
}
int mid=(l+r)/2;
build(T[u].l,l,mid);
build(T[u].r,mid+1,r);
}
void ins(int &u,int last,int l,int r,int x,int v){
u=++cnt;
T[u]=T[last];
if(l==r){
T[u].sum=v;
return;
}
int mid=(l+r)/2;
if(x<=mid) ins(T[u].l,T[last].l,l,mid,x,v);
else ins(T[u].r,T[last].r,mid+1,r,x,v);
}
int query(int o,int l,int r,int p){
if(l==r) return T[o].sum;
int mid=(l+r)/2;
if(p<=mid) return query(T[o].l,l,mid,p);
else return query(T[o].r,mid+1,r,p);
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++){
a[i]=read();
//A[i]=a[i];
}
/*sort(A+1,A+N+1);
A[0]=unique(a+1,a+n+1)-a-1;
for(int i=1;i=n;i++){
a[i]=lower_bound(A+1,a+A[0]+1,a[i])-A;
}*/
root[0]=0;
build(root[0],1,n);
for(int i=1;i<=m;i++){
int v,p,loc,val;
v=read();
p=read();
loc=read();
if(p==1){
val=read();
ins(root[i],root[v],1,n,loc,val);
}
if(p==2){
cout<<query(root[v],1,n,loc)<<endl;
root[i]=root[v];
}
}
}