求区间第K大值
#include<stdio.h>
#include<algorithm>
using namespace std;
const int M=1e5+5;
int T[20][M],S[M];
int toleft[20][M],n,m;
void build(int l=1,int r=n,int p=1){
if(l==r)return ;
int mid=l+r>>1;
int cent=S[mid];//一开始假设都是
int same=mid-l+1;
for(int i=l;i<=r;i++)
if(T[p][i]<cent)same--;//和cent相同而到左边的元素
int lid=l,rid=mid+1;
for(int i=l;i<=r;i++){
if(i==l)toleft[p][i]=0;//到左边的元素个数
else toleft[p][i]=toleft[p][i-1];
if(T[p][i]<cent){
toleft[p][i]++;
T[p+1][lid++]=T[p][i];
}
else if(T[p][i]>cent){
T[p+1][rid++]=T[p][i];
}else {
if(same){
same--;
toleft[p][i]++;
T[p+1][lid++]=T[p][i];
}else T[p+1][rid++]=T[p][i];
}
}build(l,mid,p+1);
build(mid+1,r,p+1);
}
int query(int ql,int qr,int k,int l=1,int r=n,int p=1){
if(l==r)return T[p][l];
int s1,s2,mid=l+r>>1;
if(l==ql)s1=0;//[l,ql-1]中被分配到左边的个数
else s1=toleft[p][ql-1];
s2=toleft[p][qr]-s1;//[ql,qr]中被分配到左边的个数
if(s2>=k)return query(l+s1,l+s1+s2-1,k,l,mid,p+1);
else {
int rs1=ql-1-l+1-s1;//[L,ql-1]中进入右区间的个数
int rs2=qr-ql+1-s2;//[ql,qr]中进入右区间的个数
return query(mid+1+rs1,mid+rs2+rs1,k-s2,mid+1,r,p+1);
}
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&T[1][i]);
S[i]=T[1][i];
}
sort(S+1,S+n+1);
build();
for(int i=0,ql,qr,k;i<m;i++){
scanf("%d %d %d",&ql,&qr,&k);
printf("%d\n",query(ql,qr,qr-ql+2-k));
}return 0;
}