#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N =100015;
int tree[30][N];
int a[N];
int cnt[30][N];
void build(int l,int r,int dep){
if(l==r) return;
int mid=(l+r)>>1;
int num=mid-l+1;
for(int i=l;i<=r;i++){
if(tree[dep][i]<a[mid]) num--;
}
int lpos=l;
int rpos=mid+1;
for(int i=l;i<=r;i++){
if(tree[dep][i]<a[mid]){
tree[dep+1][lpos++]=tree[dep][i];
}
else if(tree[dep][i]==a[mid]&&num>0){
tree[dep+1][lpos++]=tree[dep][i];
num--;
}
else {
tree[dep+1][rpos++]=tree[dep][i];
}
cnt[dep][i]=cnt[dep][l-1]+lpos-l;
}
build(l,mid,dep+1);
build(mid+1,r,dep+1);
}
int query(int l,int r,int st,int ed,int dep,int k){
if(st==ed) return tree[dep][st];
int mid=(l+r)>>1;
int num=cnt[dep][ed]-cnt[dep][st-1];
if(num>=k){
int ll=l+cnt[dep][st-1]-cnt[dep][l-1];
int rr=ll+num-1;
return query(l,mid,ll,rr,dep+1,k);
}
else {
int rr=ed+cnt[dep][r]-cnt[dep][ed];
int ll=rr-(ed-st-num);
return query(mid+1,r,ll,rr,dep+1,k-num);
}
}
int main(){
int t;
int n,m;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
memset(tree,0,sizeof(tree));
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
tree[0][i]=a[i];
}
sort(a+1,a+1+n);
build(1,n,0);
int r,c,k;
while(m--){
scanf("%d%d%d",&r,&c,&k);
printf("%d\n",query(1,n,r,c,0,k));
}
}
return 0;
}
学习了下划分树。
hdu 2665 Kth number 区间第K大值 划分树
最新推荐文章于 2019-08-12 10:39:36 发布