const int MAX_N=101000;
int num=0;
struct skt{
int l,r,sum;
}f[MAX_N*40];
int root[MAX_N],b[MAX_N];
void build(int k,int l,int r){
if(l==r){
f[k].sum=0;
if(k>num)
num=k;
return;
}
else{
int mid=(l+r)>>1;
f[k].l=k<<1,f[k].r=k<<1|1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
}
void add(int k,int k1,int l,int r,int x){
if(l==r){
f[k1].sum=f[k].sum;
f[k1].sum++;
return;
}
else{
int mid=(l+r)>>1;
if(x<=mid){
f[k1].l=++num;
f[k1].r=f[k].r;
add(f[k].l,f[k1].l,l,mid,x);
}
else{
f[k1].l=f[k].l;
f[k1].r=++num;
add(f[k].r,f[k1].r,mid+1,r,x);
}
f[k1].sum=f[f[k1].l].sum+f[f[k1].r].sum;
}
}
int find(int k,int k1,int l,int r,int x){
if(l==r)
return l;
else{
int mid=(l+r)>>1;
int sl=f[f[k1].l].sum-f[f[k].l].sum;
if(sl>=x){
return find(f[k].l,f[k1].l,l,mid,x);
}
else{
return find(f[k].r,f[k1].r,mid+1,r,x-sl);
}
}
}
//主席树用法
len=max_;
build(1,1,len);
for(i=1;i<=n;i++){
root[i]=++num;
add(root[i-1],root[i],1,len,b[i]);
}
for(i=0;i<m;i++){
scanf("%d%d%d",&x,&y,&z);
printf("%d\n",find(root[x-1],root[y],1,len,z));
}
离散化主席树
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX_N=201000;
int num=0;
struct skt{
int l,r,sum;
}f[MAX_N*40];
int root[MAX_N],b[MAX_N];
void build(int k,int l,int r){
if(l==r){
f[k].sum=0;
if(k>num)
num=k;
return;
}
else{
int mid=(l+r)>>1;
f[k].l=k<<1,f[k].r=k<<1|1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
}
void add(int k,int k1,int l,int r,int x){
if(l==r){
f[k1].sum=f[k].sum;
f[k1].sum++;
return;
}
else{
int mid=(l+r)>>1;
if(x<=mid){
f[k1].l=++num;
f[k1].r=f[k].r;
add(f[k].l,f[k1].l,l,mid,x);
}
else{
f[k1].l=f[k].l;
f[k1].r=++num;
add(f[k].r,f[k1].r,mid+1,r,x);
}
f[k1].sum=f[f[k1].l].sum+f[f[k1].r].sum;
}
}
int find(int k,int k1,int l,int r,int x){
if(l==r)
return l;
else{
int mid=(l+r)>>1;
int sl=f[f[k1].l].sum-f[f[k].l].sum;
if(sl>=x){
return find(f[k].l,f[k1].l,l,mid,x);
}
else{
return find(f[k].r,f[k1].r,mid+1,r,x-sl);
}
}
}
int a[MAX_N],sub_a[MAX_N],ans[MAX_N];
int main(void){
int n,m,i,x,y,z;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
sub_a[i-1]=a[i];
}
sort(sub_a,sub_a+n);
int nn=unique(sub_a,sub_a+n)-sub_a;
for(i=1;i<=n;i++){
b[i]=lower_bound(sub_a,sub_a+nn,a[i])-sub_a+1;
ans[b[i]]=a[i];
}
int len=nn;
build(1,1,len);
for(i=1;i<=n;i++){
root[i]=++num;
add(root[i-1],root[i],1,len,b[i]);
}
for(i=0;i<m;i++){
scanf("%d%d%d",&x,&y,&z);
printf("%d\n",ans[find(root[x-1],root[y],1,len,z)]);
}
return 0;
}