開始用线段树+归并排序,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; }