只是为了存模板~
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 100005;
int n,m;
int sorted[maxn];
int tree[20][maxn]; //第i层归并之后的结果
int toleft[20][maxn]; //第i层第j个数左边有几个分到左边(包括j自己)
void build(int l,int r,int d){
if(l == r) return;
int mid = (l + r) >> 1;
int same = mid - l + 1;
for(int i = l;i <= r; i++)
if(tree[d][i] < sorted[mid])
same --;
int lpos = l,rpos = mid + 1;
toleft[d][0] = 0;
for(int i = l; i <= r; i++){
toleft[d][i] = toleft[d][i - 1];
if(tree[d][i] < sorted[mid]){
tree[d + 1][lpos++] = tree[d][i];
toleft[d][i] ++;
}
else{
if(tree[d][i] == sorted[mid] && same > 0){
same --;
tree[d + 1][lpos++] = tree[d][i];
toleft[d][i] ++;
}
else
tree[d + 1][rpos++] = tree[d][i];
}
}
build(l,mid,d + 1);
build(mid + 1,r,d + 1);
}
int query(int L,int R,int l,int r,int d,int k){
//printf("%d %d %d %d %d\n",L,R,l,r,d);
if(l == r) return tree[d][l];
int mid = (L + R) >> 1;
int cnt = toleft[d][r] - toleft[d][l - 1]; //比mid小,但是不在[L,l - 1]内的数的个数
if(cnt >= k){
int newl = L + toleft[d][l - 1] - toleft[d][L - 1];
int newr = newl + cnt - 1;
return query(L,mid,newl,newr,d + 1,k);
}
else{
int newr = r + toleft[d][R] - toleft[d][r];
int newl = newr - (r - l - cnt);
return query(mid + 1,R,newl,newr,d + 1,k - cnt);
}
}
void debug(int v){
for(int i = 1; i <= n; i++)
printf("%d ",sorted[i]);
puts("");
for(int i = 1; i <= n; i++){
printf("%d ",toleft[v][i]);
}
puts("");
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
memset(tree,0,sizeof(tree));
for(int i = 1; i <= n; i++){
scanf("%d",&tree[0][i]);
sorted[i] = tree[0][i];
}
sort(sorted + 1,sorted + n + 1);
build(1,n,0);
//debug(0);
for(int i = 0; i < m; i++){
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
printf("%d\n",query(1,n,x,y,0,k));
}
}
return 0;
}