主席树模板
可持久化线段树
#include<bits/stdc++.h> #define re return #define inc(i,l,r) for(int i=l;i<=r;++i) using namespace std; template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } const int maxn=200005; int sum[maxn<<5],L[maxn<<5],R[maxn<<5]; int n,m,cnt,a[maxn],T[maxn],b[maxn]; inline int build(int l,int r) { int rt=++cnt; if(l<r) { //空,所以sum为0 int mid=(l+r)>>1; L[rt]=build(l,mid); R[rt]=build(mid+1,r); } re rt; } inline int modify(int pre,int l,int r,int x) { int rt=++cnt;//重新建点,维护此次链 L[rt]=L[pre];R[rt]=R[pre];sum[rt]=sum[pre]+1;//移花接木,复制前章 if(l==r)re rt;//返回此次修改 int mid=(l+r)>>1; if(x<=mid)L[rt]=modify(L[pre],l,mid,x); else R[rt]=modify(R[pre],mid+1,r,x);//分区 re rt; } inline int query(int pre,int now,int l,int r,int x) { if(l==r)re l; int k=sum[L[now]]-sum[L[pre]];//左区间相减 int mid=(l+r)>>1; if(k>=x)re query(L[pre],L[now],l,mid,x);//是否在左区间内 else re query(R[pre],R[now],mid+1,r,x-k); } int main() { freopen("in.txt","r",stdin); int x,y,z; rd(n),rd(m); inc(i,1,n) { rd(a[i]); b[i]=a[i]; } sort(b+1,b+n+1); int N=unique(b+1,b+n+1)-b-1; //去重排序 T[0]=build(1,N);//建立空区间 inc(i,1,n) T[i]=modify(T[i-1],1,N,lower_bound(b+1,b+N+1,a[i])-b); //依次加入 inc(i,1,m) { rd(x),rd(y),rd(z); printf("%d\n",b[query(T[x-1],T[y],1,N,z)]); } re 0; }