#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();
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgpjb25zdCBpbnQgWCA9IDFlNjsKY29uc3QgaW50IElORiA9IDFlODsKCmludCBjdyhpbnQgYSwgaW50IGIpIHsKCXJldHVybiAoYiAtIGEgKyBYKSAlIFg7Cn0KCmJvb2wgY29udGFpbnMoaW50IGwsIGludCByLCBpbnQgeCkgewoJcmV0dXJuIGN3KGwsIHgpICsgY3coeCwgcikgPT0gY3cobCwgcik7Cn0KCnN0cnVjdCBwb2ludCB7CglpbnQgeCwgeTsKCWludCBjOwoKCXBvaW50KCkge30KCXBvaW50KGludCB4XywgaW50IHlfLCBpbnQgY18pIDogeCh4XyksIHkoeV8pLCBjKGNfKSB7fQoKCWJvb2wgb3BlcmF0b3IgPCAoY29uc3QgcG9pbnQmIG8pIGNvbnN0IHsKCQlyZXR1cm4geCA+IG8ueCB8fCAoeCA9PSBvLnggJiYgeSA+IG8ueSk7Cgl9Cn07CgpzdHJ1Y3Qgbm9kZSB7Cglub2RlKiBjWzJdOwoJaW50IGx4LCByeDsKCWludCBtYXh2OwoJaW50IGxhenk7CgoJdm9pZCB1cGQoKSB7CgkJbWF4diA9IG1heChjWzBdLT5tYXh2LCBjWzFdLT5tYXh2KSArIGxhenk7Cgl9Cn07Cm5vZGUgcG9vbFsxMjM0NV07CmludCBub2RlX2lkeDsKCm5vZGUqIGluaXQoaW50IGx4LCBpbnQgcngpIHsKCW5vZGUqIHYgPSAmcG9vbFtub2RlX2lkeCsrXTsKCXYtPmNbMF0gPSB2LT5jWzFdID0gTlVMTDsKCXYtPmx4ID0gbHg7IHYtPnJ4ID0gcng7Cgl2LT5tYXh2ID0gdi0+bGF6eSA9IDA7CglpZiAobHggKyAxID09IHJ4KSB7CgkJLy8gbGVhZgoJfSBlbHNlIHsKCQl2LT5jWzBdID0gaW5pdChseCwgKGx4ICsgcngpIC8gMik7CgkJdi0+Y1sxXSA9IGluaXQoKGx4ICsgcngpIC8gMiwgcngpOwoJfQoJcmV0dXJuIHY7Cn0KCnZvaWQgdXBkX2FkZChub2RlKiB2LCBpbnQgdWx4LCBpbnQgdXJ4LCBpbnQgZGVsKSB7CglpZiAodXJ4IDw9IHYtPmx4IHx8IHYtPnJ4IDw9IHVseCkgewoJCXJldHVybjsKCX0gZWxzZSBpZiAodWx4IDw9IHYtPmx4ICYmIHYtPnJ4IDw9IHVyeCkgewoJCXYtPm1heHYgKz0gZGVsOwoJCXYtPmxhenkgKz0gZGVsOwoJfSBlbHNlIHsKCQl1cGRfYWRkKHYtPmNbMF0sIHVseCwgdXJ4LCBkZWwpOwoJCXVwZF9hZGQodi0+Y1sxXSwgdWx4LCB1cngsIGRlbCk7CgkJdi0+dXBkKCk7Cgl9Cn0KCnZvaWQgdXBkX3NldChub2RlKiB2LCBpbnQgeCwgaW50IHZhbCkgewoJaWYgKHYtPmx4ICsgMSA9PSB2LT5yeCkgewoJCXYtPm1heHYgPSBtYXgodi0+bWF4diwgdmFsKTsKCX0gZWxzZSB7CgkJdmFsIC09IHYtPmxhenk7CgkJaWYgKHggPCB2LT5jWzBdLT5yeCkgewoJCQl1cGRfc2V0KHYtPmNbMF0sIHgsIHZhbCk7CgkJfSBlbHNlIHsKCQkJdXBkX3NldCh2LT5jWzFdLCB4LCB2YWwpOwoJCX0KCQl2LT51cGQoKTsKCX0KfQoKaW50IG1heF9xdWVyeShub2RlKiB2LCBpbnQgcWx4LCBpbnQgcXJ4KSB7CglpZiAocXJ4IDw9IHYtPmx4IHx8IHYtPnJ4IDw9IHFseCkgewoJCXJldHVybiAtSU5GOwoJfSBlbHNlIGlmIChxbHggPD0gdi0+bHggJiYgdi0+cnggPD0gcXJ4KSB7CgkJcmV0dXJuIHYtPm1heHY7Cgl9IGVsc2UgewoJCXJldHVybiB2LT5sYXp5ICsgbWF4KAoJCQltYXhfcXVlcnkodi0+Y1swXSwgcWx4LCBxcngpLAoJCQltYXhfcXVlcnkodi0+Y1sxXSwgcWx4LCBxcngpKTsKCX0KfQoKdmVjdG9yPGludD4geXM7CmludCBzb2x2ZSh2ZWN0b3I8cG9pbnQ+JiBjbmRzKSB7CglpbnQgbiA9IGludChjbmRzLnNpemUoKSk7CglpZiAobiA9PSAwKSByZXR1cm4gMDsKCXlzLmNsZWFyKCk7Cglmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgeXMucHVzaF9iYWNrKGNuZHNbaV0ueSk7Cglzb3J0KHlzLmJlZ2luKCksIHlzLmVuZCgpKTsKCXlzLmVyYXNlKHVuaXF1ZSh5cy5iZWdpbigpLCB5cy5lbmQoKSksIHlzLmVuZCgpKTsKCXNvcnQoY25kcy5iZWdpbigpLCBjbmRzLmVuZCgpKTsKCW5vZGVfaWR4ID0gMDsKCW5vZGUqIHNlZ3RyZWUgPSBpbml0KDAsIGludCh5cy5zaXplKCkpKTsKCWZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CgkJcG9pbnQmIGN1ciA9IGNuZHNbaV07CgkJaW50IHkgPSBpbnQobG93ZXJfYm91bmQoeXMuYmVnaW4oKSwgeXMuZW5kKCksIGN1ci55KSAtIHlzLmJlZ2luKCkpOwoJCWlmIChjdXIuYyA9PSAwKSB7CgkJCXVwZF9hZGQoc2VndHJlZSwgeSsxLCBpbnQoeXMuc2l6ZSgpKSwgMSk7CgkJCXVwZF9zZXQoc2VndHJlZSwgeSwgbWF4X3F1ZXJ5KHNlZ3RyZWUsIDAsIHkrMSkgKyAxKTsKCQl9IGVsc2UgaWYgKGN1ci5jID09IDEpIHsKCQkJdXBkX2FkZChzZWd0cmVlLCAwLCB5KzEsIDEpOwoJCX0gZWxzZSBhc3NlcnQoZmFsc2UpOwoJfQoJcmV0dXJuIHNlZ3RyZWUtPm1heHY7Cn0KCnZlY3RvcjxpbnQ+IEwsIFI7Cgp2b2lkIHNvbHZlKCkgewoJaW50IG47CgljaW4gPj4gbjsKCUwucmVzaXplKG4pOwoJUi5yZXNpemUobik7Cglmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewoJCWNpbiA+PiBMW2ldID4+IFJbaV07Cgl9Cgl2ZWN0b3I8cG9pbnQ+IGNuZHM7CgljbmRzLnJlc2VydmUobik7CglpbnQgYW5zID0gMDsKCWZvciAoaW50IGkgPSAwOyBpIDwgbjsgaSsrKSB7CgkJaW50IGRsciA9IGN3KExbaV0sIFJbaV0pOwoJCWludCBkcmwgPSBjdyhSW2ldLCBMW2ldKTsKCQlpbnQgY3VyID0gMDsKCQljbmRzLmNsZWFyKCk7CgkJZm9yIChpbnQgaiA9IDA7IGogPCBuOyBqKyspIHsKCQkJYm9vbCBjbCA9IGNvbnRhaW5zKExbal0sIFJbal0sIExbaV0pOwoJCQlib29sIGNyID0gY29udGFpbnMoTFtqXSwgUltqXSwgUltpXSk7CgkJCWlmIChjbCAmJiBjcikgewoJCQkJY3VyICs9IDE7CgkJCX0gZWxzZSBpZiAoY2wpIHsKCQkJCWNuZHMucHVzaF9iYWNrKHBvaW50KGN3KExbaV0sIFJbal0pLCBjdyhMW2pdLCBMW2ldKSwgMSkpOwoJCQl9IGVsc2UgaWYgKGNyKSB7CgkJCQljbmRzLnB1c2hfYmFjayhwb2ludChkbHIgLSBjdyhMW2pdLCBSW2ldKSwgZHJsIC0gY3coUltpXSwgUltqXSksIDApKTsKCQkJfQoJCX0KCQljdXIgKz0gc29sdmUoY25kcyk7CgkJYW5zID0gbWF4KGFucywgY3VyKTsKCX0KCWNvdXQgPDwgYW5zIDw8ICdcbic7Cn0KCmludCBtYWluKCkgewoJaW9zOjpzeW5jX3dpdGhfc3RkaW8oMCksIGNpbi50aWUoMCk7CglpbnQgVDsKCWNpbiA+PiBUOwoJTC5yZXNlcnZlKDMwMDApOwoJUi5yZXNlcnZlKDMwMDApOwoJeXMucmVzZXJ2ZSgzMDAwKTsKCXdoaWxlIChULS0pIHNvbHZlKCk7Cn0K