#include <bits/stdc++.h>
using namespace std;

const int X = 1e6;
const int INF = 1e8;

int cw(int a, int b) {
	return (b - a + X) % X;
}

bool contains(int l, int r, int x) {
	return cw(l, x) + cw(x, r) == cw(l, r);
}

struct point {
	int x, y;
	int c;

	point() {}
	point(int x_, int y_, int c_) : x(x_), y(y_), c(c_) {}

	bool operator < (const point& o) const {
		return x > o.x || (x == o.x && y > o.y);
	}
};

struct node {
	node* c[2];
	int lx, rx;
	int maxv;
	int lazy;

	void upd() {
		maxv = max(c[0]->maxv, c[1]->maxv) + lazy;
	}
};
node pool[12345];
int node_idx;

node* init(int lx, int rx) {
	node* v = &pool[node_idx++];
	v->c[0] = v->c[1] = NULL;
	v->lx = lx; v->rx = rx;
	v->maxv = v->lazy = 0;
	if (lx + 1 == rx) {
		// leaf
	} else {
		v->c[0] = init(lx, (lx + rx) / 2);
		v->c[1] = init((lx + rx) / 2, rx);
	}
	return v;
}

void upd_add(node* v, int ulx, int urx, int del) {
	if (urx <= v->lx || v->rx <= ulx) {
		return;
	} else if (ulx <= v->lx && v->rx <= urx) {
		v->maxv += del;
		v->lazy += del;
	} else {
		upd_add(v->c[0], ulx, urx, del);
		upd_add(v->c[1], ulx, urx, del);
		v->upd();
	}
}

void upd_set(node* v, int x, int val) {
	if (v->lx + 1 == v->rx) {
		v->maxv = max(v->maxv, val);
	} else {
		val -= v->lazy;
		if (x < v->c[0]->rx) {
			upd_set(v->c[0], x, val);
		} else {
			upd_set(v->c[1], x, val);
		}
		v->upd();
	}
}

int max_query(node* v, int qlx, int qrx) {
	if (qrx <= v->lx || v->rx <= qlx) {
		return -INF;
	} else if (qlx <= v->lx && v->rx <= qrx) {
		return v->maxv;
	} else {
		return v->lazy + max(
			max_query(v->c[0], qlx, qrx),
			max_query(v->c[1], qlx, qrx));
	}
}

vector<int> ys;
int solve(vector<point>& cnds) {
	int n = int(cnds.size());
	if (n == 0) return 0;
	ys.clear();
	for (int i = 0; i < n; i++) ys.push_back(cnds[i].y);
	sort(ys.begin(), ys.end());
	ys.erase(unique(ys.begin(), ys.end()), ys.end());
	sort(cnds.begin(), cnds.end());
	node_idx = 0;
	node* segtree = init(0, int(ys.size()));
	for (int i = 0; i < n; i++) {
		point& cur = cnds[i];
		int y = int(lower_bound(ys.begin(), ys.end(), cur.y) - ys.begin());
		if (cur.c == 0) {
			upd_add(segtree, y+1, int(ys.size()), 1);
			upd_set(segtree, y, max_query(segtree, 0, y+1) + 1);
		} else if (cur.c == 1) {
			upd_add(segtree, 0, y+1, 1);
		} else assert(false);
	}
	return segtree->maxv;
}

vector<int> L, R;

void solve() {
	int n;
	cin >> n;
	L.resize(n);
	R.resize(n);
	for (int i = 0; i < n; i++) {
		cin >> L[i] >> R[i];
	}
	vector<point> cnds;
	cnds.reserve(n);
	int ans = 0;
	for (int i = 0; i < n; i++) {
		int dlr = cw(L[i], R[i]);
		int drl = cw(R[i], L[i]);
		int cur = 0;
		cnds.clear();
		for (int j = 0; j < n; j++) {
			bool cl = contains(L[j], R[j], L[i]);
			bool cr = contains(L[j], R[j], R[i]);
			if (cl && cr) {
				cur += 1;
			} else if (cl) {
				cnds.push_back(point(cw(L[i], R[j]), cw(L[j], L[i]), 1));
			} else if (cr) {
				cnds.push_back(point(dlr - cw(L[j], R[i]), drl - cw(R[i], R[j]), 0));
			}
		}
		cur += solve(cnds);
		ans = max(ans, cur);
	}
	cout << ans << '\n';
}

int main() {
	ios::sync_with_stdio(0), cin.tie(0);
	int T;
	cin >> T;
	L.reserve(3000);
	R.reserve(3000);
	ys.reserve(3000);
	while (T--) solve();
}
