開始用线段树+归并排序,4700+ms飘过~,后来去学划分树。尽管还不是非常懂,只是就这样吧
#include<iostream>
#include<algorithm>
#define maxn 100010
using namespace std;
int n,m;
int nsort[maxn];
int nleft[30][maxn],tree[30][maxn];
void build(int l,int r,int c)
{
if(l==r) return;
int mid=(l+r)/2;
int sum=mid-l+1;
for(int i=l;i<=r;i++)
{
if(tree[c][i]<nsort[mid]) sum--;
}
int ll=l,rr=mid+1;
for(int i=l;i<=r;i++)
{
if(tree[c][i]<nsort[mid]) tree[c+1][ll++]=tree[c][i];
else if(tree[c][i]==nsort[mid]&&sum>0) tree[c+1][ll++]=tree[c][i],sum--;
else tree[c+1][rr++]=tree[c][i];
nleft[c][i]=nleft[c][l-1]+ll-l;
}
build(l,mid,c+1);
build(mid+1,r,c+1);
}
int que(int l,int r,int a,int b,int k,int c)
{
if(a==b) return tree[c][a];
int mid=(l+r)/2;
int cnt=nleft[c][b]-nleft[c][a-1];
if(cnt>=k)
{
int nl=l+nleft[c][a-1]-nleft[c][l-1];
int nr=nl+cnt-1;
return que(l,mid,nl,nr,k,c+1);
}
else
{
int nr=b+nleft[c][r]-nleft[c][b];
int nl=nr-(b-a-cnt);
return que(mid+1,r,nl,nr,k-cnt,c+1);
}
}
int main()
{
cin.sync_with_stdio(false);
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>tree[0][i];
nsort[i]=tree[0][i];
}
sort(nsort+1,nsort+n+1);
build(1,n,0);//l,r,层。
while(m--)
{
int a,b,k;
cin>>a>>b>>k;
cout<<que(1,n,a,b,k,0)<<endl;
}
}
return 0;
}