/*
分析:
二分+划分树。
求某个区间,小于给定的数的数的数量= =(既:有多少
数小于给定的数...)
刚学划分树,自己没想到,囧~~~。
既然要求某个指定区间小于h的元素的数量,那么可以
用二分枚举来枚举出这个区间的第mid大值,如果这个值<=h,
那么就说明这个区间至少有mid个数是符合情况的,so。。。
2013-04-01
*/
#include"iostream"
#include"cstdio"
#include"cstring"
#include"algorithm"
using namespace std;
const int N=20;
const int M=100111;
int n,m;
int tr[N][M],toleft[N][M],sorted[M];
void build(int l,int r,int k)
{
if(l==r) return ;
int i;
int mid,equ,ln,rn;
mid=(l+r)>>1;equ=0;ln=l;rn=mid+1;
for(i=mid;i>=l;i--)
{
if(sorted[i]==sorted[mid]) equ++;
else break;
}
for(i=l;i<=r;i++)
{
toleft[k][i]=toleft[k][i-1];
if(tr[k][i]<sorted[mid])
{
tr[k+1][ln++]=tr[k][i];
toleft[k][i]++;
}
else if(tr[k][i]==sorted[mid])
{
if(equ) {tr[k+1][ln++]=tr[k][i];equ--;toleft[k][i]++;}
else tr[k+1][rn++]=tr[k][i];
}
else tr[k+1][rn++]=tr[k][i];
}
build(l,mid,k+1);
build(mid+1,r,k+1);
}
int query(int a,int b,int aim,int l,int r,int k)
{
if(l==r) return tr[k][l];
int mid,p,pp;
mid=(l+r)>>1;
p=toleft[k][a-1]-toleft[k][l-1];
pp=toleft[k][b]-toleft[k][a-1];
if(pp>=aim) return query(l+p,l+p+pp-1,aim,l,mid,k+1);
else
{
int z,zz;
z=a-l-p;
zz=b-a+1-pp;
return query(mid+z+1,mid+z+zz,aim-pp,mid+1,r,k+1);
}
}
int solve(int a,int b,int c)
{
int ans=0;
int low,mid,up,temp;
low=1;up=b-a+1;
while(low<=up)
{
mid=(low+up)>>1;
temp=query(a,b,mid,1,n,0);
if(temp<=c) {ans=mid;low=mid+1;}
else up=mid-1;
}
return ans;
}
int main()
{
int T,Case;
int i;
int a,b,c;
cin>>T;
for(Case=1;Case<=T;Case++)
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++) {scanf("%d",&tr[0][i]);sorted[i]=tr[0][i];}
sort(sorted+1,sorted+n+1);
toleft[0][0]=0;
build(1,n,0);
printf("Case %d:\n",Case);
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
a++;b++;
printf("%d\n",solve(a,b,c));
}
}
return 0;
}