题目
luogu3834
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define N 500005
#define M 10000000
using namespace std;
int n,m,rk[N];
int root[N];
struct data{int id,num;}a[N];
bool cmp(data x,data y){return x.num<y.num;}
struct node{int l,r,sz;}T[M];
int cnt;
void insert(int &rt,int x,int y,int p)
{
T[++cnt]=T[rt];rt=cnt;
T[rt].sz++;//sz记录子树中被标记的结点个数
if(x==y) return;
int mid=(x+y)>>1;
if(p<=mid) insert(T[rt].l,x,mid,p);
else insert(T[rt].r,mid+1,y,p);
}
int query(int ql,int qr,int x,int y,int k)
{
if(x==y) return x;
int t=T[T[qr].l].sz-T[T[ql].l].sz;
int mid=(x+y)>>1;
if(k<=t) return query(T[ql].l,T[qr].l,x,mid,k);
else return query(T[ql].r,T[qr].r,mid+1,y,k-t);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i].num),a[i].id=i;
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++) rk[a[i].id]=i;//rk[i]记录在原序列的位置为i的数是第几大
for(int i=1;i<=n;i++)
{
root[i]=root[i-1];//root[i]记录前i个数构成的线段树的根
insert(root[i],1,n,rk[i]);
}
for(int i=1;i<=m;i++)
{
int x,y,k;scanf("%d%d%d",&x,&y,&k);
printf("%d\n",a[query(root[x-1],root[y],1,n,k)].num);//类比sum[r]-sum[i-1]
}
return 0;
}