#include<bits/stdc++.h>
#define M 200005
using namespace std;
int n,T;
int tot,cnt,it;
int a[M],lsh[M],rx[M],ly[M<<5],ry[M<<5],sum[M<<5];
void read(int &x) {
int f=1;x=0;char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+(c^48);c=getchar();}
x*=f;
}
void write(int x){
if(x<=9){
putchar(x+'0');
return;
}
write(x/10);
putchar(x%10+'0');
}
void build(int &s,int l,int r){//建树
s=++tot;//加点
if(l==r) return;
int mid=(l+r)>>1;
build(ly[s],l,mid);
build(ry[s],mid+1,r);
}
int update(int x,int l,int r){//建权值线段树
int y=++tot;
ly[y]=ly[x];ry[y]=ry[x];sum[y]=sum[x]+1;//继承上一棵线段树
if(l==r) return y;
int mid=(l+r)>>1;//寻找需要更新的链
if(it<=mid) ly[y]=update(ly[y],l,mid);
else ry[y]=update(ry[y],mid+1,r);
return y;
}
int query(int u,int v,int l,int r,int k){//查询
int ans;
int mid=(l+r)>>1,x=sum[ly[v]]-sum[ly[u]];//第r棵线段树左儿子-第(l-1)棵线段树左儿子的值
if(l==r) return l;//找到
if(x>=k) ans=query(ly[u],ly[v],l,mid,k);
else ans=query(ry[u],ry[v],mid+1,r,k-x);
return ans;
}
int main(){
scanf("%d %d",&n,&T);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
lsh[i]=a[i];
}
sort(lsh+1,lsh+n+1);
cnt=unique(lsh+1,lsh+n+1)-lsh-1;
build(rx[0],1,cnt);
for(int i=1;i<=n;i++){
it=lower_bound(lsh+1,lsh+cnt+1,a[i])-lsh;//查找最小下标的匹配值
rx[i]=update(rx[i-1],1,cnt);
}
while(T--) {
int L,R,k;
scanf("%d %d %d",&L,&R,&k);
int ans=query(rx[L-1],rx[R],1,cnt,k);
printf("%d\n",lsh[ans]); //[l,r]就等价于 第r棵线段树-第(l-1)棵线段树 的k小值,返回该节点映射的值
}
return 0;
}
【模板】主席树
最新推荐文章于 2024-08-06 17:25:28 发布