主席树:可持久化权值线段树
模板(查询区间第k大,单点修改):luogu【模板】可持久化线段树2
利用了前缀和的思想,动态开点
利用已有的且不变动的部分减小空间复杂度
#include<bits/stdc++.h>
#define ll long long
#define maxn 200010
using namespace std;
int n,m;
ll a[maxn];//原数组
ll b[maxn];//离散化数组
int tot;
struct node{
int l,r,sum;
}e[maxn*50];
int cnt,rot[maxn];//根节点数组
void insert(int l,int r,int pre,int &now,int k){
e[++cnt]=e[pre];
now=cnt;
e[now].sum++;
if(l==r)return ;
int mid=(l+r)>>1;
if(k<=mid)insert(l,mid,e[pre].l,e[now].l,k);
else insert(mid+1,r,e[pre].r,e[now].r,k);
}
int query(int l,int r,int L,int R,int k){
if(l==r){
return l;
}
int mid=(l+r)>>1;
int res=e[e[R].l].sum-e[e[L].l].sum;
if(k<=res)return query(l,mid,e[L].l,e[R].l,k);
else return query(mid+1,r,e[L].r,e[R].r,k-res);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
tot=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++){
int k=lower_bound(b+1,b+tot+1,a[i])-b;
insert(1,n,rot[i-1],rot[i],k);
}
for(int L,R,k,i=1;i<=m;i++){
scanf("%d%d%d",&L,&R,&k);
cout<<b[query(1,n,rot[L-1],rot[R],k)]<<endl;
}
return 0;
}