划分树
参考资料:百度百科

1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 6 #define N 100500 7 8 #define MID ((l+r)>>1) 9 int a[N],s[N],t[20][N],num[20][N],n,m; 10 11 void Build(int c,int l,int r) 12 { 13 int lm=MID-l+1,lp=l,rp=MID+1; 14 for(int i=l;i<=MID;i++) 15 lm-=s[i]<s[MID]; 16 for(int i=l;i<=r;i++) 17 { 18 if( i==l ) 19 num[c][i]=0; 20 else 21 num[c][i]=num[c][i-1]; 22 if( t[c][i]==s[MID] ) 23 { 24 if( lm ) 25 { 26 lm--; 27 num[c][i]++; 28 t[c+1][lp++]=t[c][i]; 29 } 30 else 31 t[c+1][rp++]=t[c][i]; 32 } 33 else if( t[c][i]<s[MID] ) 34 { 35 num[c][i]++; 36 t[c+1][lp++]=t[c][i]; 37 } 38 else 39 t[c+1][rp++]=t[c][i]; 40 } 41 if( l<r ) 42 Build(c+1,l,MID),Build(c+1,MID+1,r); 43 } 44 45 int Query(int c,int l,int r,int ql,int qr,int k) 46 { 47 if( l==r ) 48 return t[c][l]; 49 int s,ss; 50 if( l==ql ) 51 s=0,ss=num[c][qr]; 52 else 53 s=num[c][ql-1],ss=num[c][qr]-num[c][ql-1]; 54 if( k<=ss ) 55 return Query(c+1,l,MID,l+s,l+s+ss-1,k); 56 else 57 return Query(c+1,MID+1,r,MID+1+ql-l-s,MID+1+qr-l-s-ss,k-ss); 58 } 59 60 int main() 61 { 62 scanf("%d%d",&n,&m); 63 for(int i=1;i<=n;i++) 64 { 65 scanf("%d",&a[i]); 66 s[i]=t[0][i]=a[i]; 67 } 68 sort(s+1,s+1+n); 69 Build(0,1,n); 70 while( m-- ) 71 { 72 int l,r,k; 73 scanf("%d%d%d",&l,&r,&k); 74 printf("%d\n",Query(0,1,n,l,r,k)); 75 } 76 return 0; 77 }