#include <bits/stdc++.h>
using namespace std;
const int MAX_N=1e6+10;
struct node{
int i,l,r,pos;
}que[MAX_N];
//第i个询问的左右区间,分块位置
bool cmp(node a,node b)
{
return a.pos==b.pos?a.r<b.r:a.l<b.l;
//处于相同分块比较左区间,否则比较右区间
}
int a[MAX_N],cnt[MAX_N],ans[MAX_N],sum;
void add(int i)
{
if(cnt[a[i]]==0)
sum++;
cnt[a[i]]++;
}
void del(int i)
{
cnt[a[i]]--;
if(cnt[a[i]]==0)
sum--;
}
void init()
{
fill(a,a+MAX_N,0);
fill(cnt,cnt+MAX_N,0);
fill(ans,ans+MAX_N,0);
sum=0;
}
int main()
{
int t,n,m;
while(~scanf("%d",&t))
{
for(int k=1;k<=t;k++)
{
init();
scanf("%d%d",&n,&m);
printf("Case %d:\n",k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int Size=n/sqrt(m);//分块大小为n/sqrt(m)时,复杂度最小
for(int i=1;i<=m;i++)
{
scanf("%d%d",&que[i].l,&que[i].r);
que[i].pos=que[i].l/Size;
que[i].i=i;
}
sort(que+1,que+m+1,cmp);
int L=1,R=0,l,r;
for(int i=1;i<=m;i++)
{
l=que[i].l;r=que[i].r;
while(l<L) add(--L);
while(r<R) del(R--);
while(L<l) del(L++);
while(R<r) add(++R);
ans[que[i].i]=sum;
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
}
return 0;
}