/*
   线段树 +  离散化
    
   好像记得暑假做 树状数组的时候 做过一个离散化的题目, 当时是用2分查询
   离散节点标记的, 速度还是可以的, 不过那时对离散化也没有什么概念, 大
   概是没怎么接触, 今天做了这道题目的时候,  也算是明白了 离散化 的基本
   意思,因为 题目的 数据范围很大 , 1- 10000000,直接线段树的话, 先不说
   内存会不会爆, 这么大的范围估计也是 TLE了. 
   仔细读题, 可以看到  1<= N <= 10000, 也就是说 最多只有 10000个点, 如果
   每个点都不同, 那么最多也只有 20000 个数据, 那么离散后的 范围就相当小;
   
   离散化 的大概思路 :   比如说给你一组 数据 1 4 1000 100000,  如果直接
                         开线段, 显然是浪费, 那么我们只要 进行 映射 :
                                1    1  
                                4    2
                             1000    3
                           100000    4
                         接下来 我们只要对 1 2 3 4 建立线段树就行了 只需要
                         [1,4]的区间     
*/
/*
Mail to   : miyubai@gamil.com
Link      : http://www.cnblogs.com/MiYu  || http://www.cppblog.com/MiYu
Author By : MiYu
Test      : 1
Complier  : g++ mingw32-3.4.2
Program   : 2528
Doc Name  : Mayor's posters
*/
//#pragma warning( disable:4789 )
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <utility>
#include <queue>
#include <stack>
#include <list>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
using namespace std;
int T, N, x, y;
map < int, int > mp;
set <int> st;
map<int,int>::iterator beg, end;
struct segtree {
       int left, right,cov;
       int mid () { return (left+right)>>1; }
}seg[80010];
struct P {  //节点数据 
       int left, right;
}pp[10010];
void creat ( int x, int y, int rt = 1 ) {
     seg[rt].left = x;
     seg[rt].right = y;
     seg[rt].cov = 0;
     if ( x == y ) return ;
     int mid = seg[rt].mid();
     creat ( x, mid, rt << 1 );
     creat ( mid + 1, y, rt << 1 | 1 );     
}
void insert ( int x, int y, int flag, int rt = 1 ) {
     //如果线段被覆盖, 直接标记, 返回 
    if ( seg[rt].left == x && seg[rt].right == y ) {
        seg[rt].cov = flag;
        return;   
    }    
    int LL = rt << 1, RR = rt << 1 | 1, mid = seg[rt].mid();
    if ( seg[rt].cov != -1 ) {  
       //如果线段是被覆盖的 , 标记下传, 同时自身标记-1,表示有多个标记 
        seg[LL].cov = seg[RR].cov = seg[rt].cov;
        seg[rt].cov = -1;   
    }
    //递归 插入 
    if ( y <= mid ) insert ( x, y, flag, LL );
    else if ( x > mid ) insert ( x, y, flag, RR );
    else {
          insert ( x, mid, flag, LL );
          insert ( mid + 1, y, flag, RR );     
    }
}
void query ( int x, int y, int rt = 1 ) {
    // 线段被覆盖 , 将覆盖标记 放入 set 
    if ( seg[rt].cov != -1 && seg[rt].left == x && seg[rt].right == y ) {
        st.insert ( seg[rt].cov );
        return ;   
    }else {//递归查询 
          int LL = rt << 1, RR = rt << 1 | 1, mid = seg[rt].mid();
          if ( y <= mid ) query ( x, y, rt << 1 ); 
          else if ( x > mid ) query ( x, y, rt << 1 | 1 );
          else {
                query ( x, mid, LL );
                query ( mid + 1, y, RR );     
          }
    }
}
void print () {
     for ( set<int>::iterator it = st.begin(); it != st.end(); ++ it )
           cout << *it << endl;     
}
int main ()
{
    scanf ( "%d", &T );
    creat ( 1, 20010 );
    while ( T -- ) {
           mp.clear();
           st.clear (); 
           scanf ( "%d", &N );
           for ( int i = 1; i <= N; ++ i ) {
                scanf ( "%d%d", &pp[i].left, &pp[i].right );
                 //map 去重 
                mp[pp[i].left] = 88; mp[pp[i].right] = 88;    
           }      
           beg = mp.begin(), end = mp.end();
           //因为map 已经自动排序了,所以直接从 1 --> N 开始标记, 离散化 
           for ( int i = 1;beg != end; ++ beg, ++ i ) {         
                beg->second = i;  
           }
           //因为线段树已经建立好了, 所以没必要每次都重建一次, 只要插入一条
           //覆盖所有区间的 底板 就行了 
           insert ( 1, N * 2, 0 );
           for ( int i = 1; i <= N; ++ i ) {
                //用离散后的标记 插入 线段 
                insert ( mp[pp[i].left], mp[pp[i].right], i );   
           }
           query ( 1, N * 2 );
           //print();
           int cnt = st.size();
           if ( *st.begin() == 0 ) -- cnt; 
           printf ( "%d\n", cnt );
    }
    return 0;
}