/*
离散化+线段树
由于 数据的输入最大是 10000000 ,直接用开数组肯点会超,所以要将起离散话,
首先 ,我们存储输入的边,将其离散化,后面的就和一般的线段树一样可。
*/
#include<stdio.h>
#include<stdlib.h>
#define N 10040
struct node
{
int l;
int r;
}p[N*2];
struct color
{
int l;
int r;
int c;
}q[N*8];
int cmp ( const void *a , const void *b )
{
return *(int *)a - *(int *)b;
}
int addre[N*4],sum,m,pos[N*4],vis[N];
void build(int x,int l,int r)
{
q[x].l=l;
q[x].r=r;
q[x].c=0;
if(l==r)return ;
int mid=(l+r)/2;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
}
int find(int x)//离散化后的查询
{
int head=1,tail=m-1;
while(head<=tail)
{
int mid=(head+tail)/2;
if(addre[mid]==x)return mid;
if(addre[mid]<x)head=mid+1;
else
if(addre[mid]>x)tail=mid-1;
}
return 0;
}
void change(int x,int l,int r,int color)
{
if(q[x].l==l&&q[x].r==r)
{
q[x].c=color;
return ;
}
if(q[x].c!=-1)//下分到子节点
{
q[x*2].c=q[x].c;
q[x*2+1].c=q[x].c;
q[x].c=-1;
}
int mid=(q[x].l+q[x].r)/2;
if(r<=mid)change(x*2,l,r,color);
else
{
if(l>mid)change(x*2+1,l,r,color);
else
{
change(x*2,l,mid,color);
change(x*2+1,mid+1,r,color);
}
}
}
void Get(int x,int l,int r)
{
if(q[x].c==0)return ;
if(q[x].c!=-1)
{
if(!vis[q[x].c])//避免重复计算
{
vis[q[x].c]=1;
sum++;
}
return ;
}
int mid=(q[x].l+q[x].r)/2;
if(r<=mid)Get(x*2,l,r);
else
{
if(l>mid)Get(x*2+1,l,r);
else
{
Get(x*2,l,mid);
Get(x*2+1,mid+1,r);
}
}
}
int main()
{
int T,n,i;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int k=1;
for(i=1;i<=n;i++)
{
scanf("%d%d",&p[i].l,&p[i].r);
pos[k++]=p[i].l;
pos[k++]=p[i].r;
}
qsort(pos,k,sizeof(pos[0]),cmp);
addre[1]=pos[1];
m=2;
for(i=1;i<=k;i++)
{
if(pos[i]!=pos[i-1])
{
addre[m++]=pos[i];//离散化,用原来点的下标,来代替点,实现离散化
}
}
build(1,1,m-1);
for(i=1;i<=n;i++)
{
int l=find(p[i].l);//离散化,用原来点的下标,来代替点,实现离散化
int r=find(p[i].r);
change(1,l,r,i);
}
sum=0;
for(i=0;i<=n;i++)vis[i]=0;
Get(1,1,m-1);
printf("%d\n",sum);
}
}