// Model solution for problem G // Author: Bartosz Walczak #include #include #include #include struct interval { int l, r; }; inline std::istream& operator>>(std::istream& in, interval& dst) { return in >> dst.l >> dst.r; } inline std::ostream& operator<<(std::ostream& out, const interval& src) { return out << src.l << " " << src.r; } struct node; struct info_t { int count; int diff; node* loose; node* tight; info_t() : count(0), diff(std::numeric_limits::max()), loose(nullptr), tight(nullptr) {} info_t(info_t left, node* p, info_t right); }; struct node : interval { int active; int bound; info_t info; }; info_t::info_t(info_t left, node* p, info_t right) : count(left.count + p->active + right.count), diff(std::numeric_limits::max()), loose(nullptr), tight(nullptr) { int tight_value = std::numeric_limits::max(); int loose_value = std::numeric_limits::max(); if (left.tight) { diff = left.diff; tight_value = left.tight->r; tight = left.tight; } if (left.loose) { loose_value = left.loose->r; loose = left.loose; } if (p->active and p->bound - left.count - 1 < diff) { diff = p->bound - left.count - 1; if (p->r < loose_value) { tight_value = p->r; tight = p; } else { tight_value = loose_value; tight = loose; } } if (p->active and p->r < loose_value) { loose_value = p->r; loose = p; } if (right.tight and right.diff - left.count - p->active < diff) { diff = right.diff - left.count - p->active; if (right.tight->r < loose_value) { tight_value = right.tight->r; tight = right.tight; } else { tight_value = loose_value; tight = loose; } } if (right.loose and right.loose->r < loose_value) { loose_value = right.loose->r; loose = right.loose; } } inline info_t get_info(node* first, node* last) { return (first >= last) ? info_t() : first[(last-first)/2].info; } void update(node* first, node* last, node* left, node* right) { if (first >= last) return; node* middle = first+(last-first)/2; if (middle > left) update(first, middle, left, right); if (middle+1 < right) update(middle+1, last, left, right); middle->info = info_t(get_info(first, middle), middle, get_info(middle+1, last)); } void testcase() { std::size_t n; std::cin >> n; std::vector data(n); for (interval& i : data) std::cin >> i; std::sort(data.begin(), data.end(), [](const node& a, const node& b) { return a.l < b.l; }); std::vector order(n); std::size_t lower = 0, upper = n-1; for (;;) { for (node& d : data) { d.active = 1; d.bound = static_cast(n); } update(&data[0], &data[n], &data[0], &data[n]); std::size_t k = (lower+upper)/2; bool result = true; node* coverage = &data[0]; for (std::size_t i=0; i(i)) { result = false; break; } order[i] = *info.tight; info.tight->active = 0; update(&data[0], &data[n], info.tight, info.tight+1); if (i+k+1 >= n) continue; node* old_coverage = coverage; while (coverage < &data[n] and coverage->l <= info.tight->r) coverage++->bound = static_cast(i+k+1); update(&data[0], &data[n], old_coverage, coverage); } if (lower == upper) { std::cout << lower << std::endl; for (interval& i : order) std::cout << i << std::endl; return; } if (result) upper = k; else lower = k+1; } } int main() { std::size_t t; for (std::cin >> t; t; --t) testcase(); return 0; }