unique 返回的是去重后的尾地址,所以减去初始地址。从第一位开始,就还要-1(与lower_bound不同)
切记,没有排序前只是去掉相邻的重复元素,如果要真正去重就要排序。所以先sort再unique
去重是因为:线段树的各叶节点不能重复。而出现的次数不要紧,因为每加入一个数,会更新一个版本的树
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int tot,n,m,ver[maxn],a[maxn],b[maxn];
struct tt{
int l,r,val;
}tree[maxn<<5];//n是maxn <<5是logn,可开大一点
int build(int l,int r){
int rt=++tot;
tree[rt].val=0;
tree[rt].l=rt;
tree[rt].r=rt;
return rt;
}
void pushup(int root){
tree[root].val=tree[tree[root].l].val+tree[tree[root].r].val;
}
int change(int node,int l,int r,int pos){
int root=++tot;
tt &rt=tree[root];
rt=tree[node];
if(l==r){
rt.val++;
return root;
}
int mid=(l+r)>>1;
if(pos<=mid) rt.l=change(rt.l,l,mid,pos);
else rt.r=change(rt.r,mid+1,r,pos);
pushup(root);
return root;
}
int query(int per,int lst,int l,int r,int k){
if(l==r) return l;
tt &pp=tree[per],&ll=tree[lst];
int tx=tree[ll.l].val-tree[pp.l].val;
int mid=(l+r)>>1;
if(tx>=k) return query(pp.l,ll.l,l,mid,k);
else return query(pp.r,ll.r,mid+1,r,k-tx);
}
int main(){
int x,l,r,k,len;
tot=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
len=unique(b+1,b+1+n)-(b+1);
ver[0]=build(1,len);
//去重,并求有几个不重复的数
for(int i=1;i<=n;i++){
int tem=lower_bound(b+1,b+1+len,a[i])-b;//离散化
ver[i]=change(ver[i-1],1,len,tem);
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",b[query(ver[l-1],ver[r],1,len,k)]);
}
return 0;
}