主席树,区间第$k$大。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-8; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } template <class T> inline void read(T &x) { char c = getchar(); x = 0;while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } } const int maxn=100010; int a[maxn],b[maxn],root[maxn],n,m,sz; struct Node {int l,r,sum;} s[maxn*40]; int get(int x) { int L=1,R=n,res; while(L<=R) { int mid=(L+R)/2; if(b[mid]>x) R=mid-1; else if(b[mid]<x) L=mid+1; else res=mid,R=mid-1; } return res; } void update(int l,int r,int &x,int y,int p) { sz++; s[sz]=s[y]; s[sz].sum++; x=sz; if(l==r) return; int mid=(l+r)/2; if(p<=mid) update(l,mid,s[sz].l,s[y].l,p); else update(mid+1,r,s[sz].r,s[y].r,p); } int quary(int l,int r,int x,int y,int p) { if(l==r) return l; int mid=(l+r)/2; int tmp=s[s[y].l].sum-s[s[x].l].sum; if(tmp>=p) return quary(l,mid,s[x].l,s[y].l,p); else return quary(mid+1,r,s[x].r,s[y].r,p-tmp); } 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+1+n); for(int i=1;i<=n;i++) a[i]=get(a[i]); for(int i=1;i<=n;i++) update(1,n,root[i],root[i-1],a[i]); for(int i=1;i<=m;i++) { int L,R,k; scanf("%d%d%d",&L,&R,&k); printf("%d\n",b[quary(1,n,root[L-1],root[R],k)]); } return 0; }