资料1:http://blog.csdn.net/regina8023/article/details/41910615
资料2:模板来源:http://www.cnblogs.com/lidaxin/category/794693.html
主席树主要是维护区间在第i个数插入之后,每个区间内的数出现的次数,这样就需要维护n颗线段树。
可持久化在于它可以保存前面任意第i个数插入时的区间情况
同时每颗树结构都是一样的,因此可以相减得到特定区间的情况
#include <queue>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define inf 1000000000LL
#define mod 1000000007
using namespace std;
ll read()
{
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int N=1e5+10;
const int M=N*20+10;
int tot,sz;
int root[N],ls[M],rs[M];
ll sum[M];
int v[N],ha[N];
void update(int l,int r,int x,int &y,int v)
{
y=++sz;
sum[y]=sum[x]+1;
if(l==r)return;
ls[y]=ls[x];rs[y]=rs[x];
int mid=(l+r)>>1;
if(v<=mid)update(l,mid,ls[x],ls[y],v);
else update(mid+1,r,rs[x],rs[y],v);
}
int que(int L,int R,int rk)
{
int l=1,r=tot,mid,x,y;
x=root[L-1];y=root[R];
while(l<r)
{
int mid=(l+r)>>1;
int now=sum[ls[y]]-sum[ls[x]];
if(rk<=now) r=mid,x=ls[x],y=ls[y];
else l=mid+1,rk-=now,x=rs[x],y=rs[y];
}
return ha[l];
}
int main(){
int n=read(),m=read();
for(int i=1;i<=n;i++)
v[i]=read(),ha[i]=v[i];
sort(ha+1,ha+1+n);
tot=unique(ha+1,ha+1+n)-ha-1;
for(int i=1;i<=n;i++)
v[i]=lower_bound(ha+1,ha+1+tot,v[i])-ha;
for(int i=1;i<=n;i++)
update(1,tot,root[i-1],root[i],v[i]);
int x,y,z;
for(int i=1;i<=m;i++) {
x=read(),y=read(),z=read();
printf("%d
",que(x,y,z));
}
return 0;
}