最简单静态主席树求第k小
可持续数据结构适厉害
但是效率方面还有点搞不清楚 主要是和普通线段树的二分做法不感觉有什么优势
蒟蒻真的很费解 还望大牛赐教
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 111111
#define mid ((l+r)>>1)
int ls[maxn*20],rs[maxn*20],sum[maxn*20];
int uni[maxn],real[maxn],t[maxn];
int cnt;
int scan()
{
int res=0,ch;
while(!((ch= getchar())>='0'&&ch<='9')){
if(ch==EOF)return 1<<30;
}
res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
res=res*10+(ch-'0');
return res;
}
void build(int &rt,int l,int r){
rt=++cnt;
sum[rt]=0;
if(l==r)return ;
build(ls[rt],l,mid);
build(rs[rt],mid+1,r);
}
void ins(int &rt,int last,int l,int r,int pos){
rt=++cnt;
sum[rt]=sum[last]+1;ls[rt]=ls[last],rs[rt]=rs[last];
if(l==r)return ;
if(pos<=mid)ins(ls[rt],ls[last],l,mid,pos);
else ins(rs[rt],rs[last],mid+1,r,pos);
}
int query(int now,int past,int l,int r,int k){
if(l==r)return l;
int x=sum[ls[now]]-sum[ls[past]];
if(x>=k)return query(ls[now],ls[past],l,mid,k);
else return query(rs[now],rs[past],mid+1,r,k-x);
}
int n,m;
int main(){
int _;
_=scan();
while(_--){
cnt=0;
n=scan();m=scan();
for(int i=1;i<=n;++i){
real[i]=scan();
uni[i]=real[i];
}
sort(uni+1,uni+1+n);
int all=(int)(unique(uni+1,uni+1+n)-uni-1);
build(t[0],1,all);
for(int i=1;i<=n;++i){
real[i]=(int)(lower_bound(uni+1,uni+1+all,real[i])-uni);
ins(t[i],t[i-1],1,all,real[i]);
}
int l,r,k;
while(m--){
l=scan();r=scan();k=scan();
printf("%d\n",uni[query(t[r],t[l-1],1,all,k)]);
}
}
return 0;
}