1 //hdu 2665 2 #include <iostream> 3 #include <cstdio> 4 #include <algorithm> 5 #include <cstring> 6 7 using namespace std; 8 9 #define ls rt<<1 10 #define rs rt<<1|1 11 #define lson l,m,ls 12 #define rson m+1,r,rs 13 14 #define MAXN 100010 15 16 int len; 17 int sorted[MAXN]; 18 int toLeft[20][MAXN],val[20][MAXN]; 19 20 void build(int d,int l,int r) 21 { 22 if(l==r)return; 23 int m=(l+r)>>1; 24 int lsame=m-l+1;//lsame表示和val_mid相等且分到左边的 25 for(int i=l;i<=r;i++) 26 if(val[d][i]<sorted[m]) 27 lsame--;////先假设左边的数(mid - l + 1)个都等于val_mid,然后把实际上小于val_mid的减去 28 int lpos=l; 29 int rpos=m+1; 30 int same=0; 31 for(int i=l;i<=r;i++) 32 { 33 if(i==l) 34 { 35 toLeft[d][i]=0;//toLeft[i]表示[ l , i ]区域里有多少个数分到左边 36 } 37 else 38 { 39 toLeft[d][i]=toLeft[d][i-1]; 40 } 41 if(val[d][i]<sorted[m]) 42 { 43 toLeft[d][i]++; 44 val[d+1][lpos++]=val[d][i]; 45 } 46 else if(val[d][i]>sorted[m]) 47 { 48 val[d+1][rpos++]=val[d][i]; 49 } 50 else 51 { 52 if(same<lsame)//有lsame的数是分到左边的 53 { 54 same++; 55 toLeft[d][i]++; 56 val[d+1][lpos++]=val[d][i]; 57 } 58 else 59 { 60 val[d+1][rpos++]=val[d][i]; 61 } 62 } 63 } 64 build(d+1,l,m); 65 build(d+1,m+1,r); 66 } 67 68 69 int query(int L,int R,int k,int d,int l,int r) 70 { 71 if(l==r) return val[d][l]; 72 int s;//s表示[ L , R ]有多少个分到左边 73 int ss;//ss表示 [l , L-1 ]有多少个分到左边 74 int m=(l+r)>>1; 75 if(L==l) 76 { 77 s=toLeft[d][R]; 78 ss=0; 79 } 80 else 81 { 82 s=toLeft[d][R]-toLeft[d][L-1]; 83 ss=toLeft[d][L-1]; 84 } 85 if(s>=k)//有多于k个分到左边,显然去左儿子区间找第k个 86 return query(l+ss,l+ss+s-1,k,d+1,l,m); 87 else 88 return query(m+L-l-ss+1,m-l-ss+R-s+1,k-s,d+1,m+1,r); 89 } 90 int main() 91 { 92 int n,m,t; 93 scanf("%d",&t); 94 while(t--) 95 { 96 scanf("%d%d",&n,&m); 97 for(int i=1;i<=n;i++) 98 { 99 scanf("%d",&val[0][i]); 100 sorted[i]=val[0][i]; 101 } 102 sort(sorted+1,sorted+n+1); 103 build(0,1,n); 104 while(m--) 105 { 106 int l,r,k; 107 scanf("%d%d%d",&l,&r,&k); 108 printf("%d\n",query(l,r,k,0,1,n)); 109 } 110 } 111 return 0; 112 }