I Intervals on the Ring
题意
一个长度为 n n n 的圆排列上有 k k k 段连续区间,现要构造 m m m 个连续区间,使得这 m m m 个连续区间的交集为的圆排列上的 k k k 段连续区间
先考虑圆排列上有 2 2 2 段连续区间时,假设为 [ A , B ] , [ C , D ] [A,B], [C,D] [A,B],[C,D],那么很显然选择 [ A , D ] , [ C , B ] [A,D],[C,B] [A,D],[C,B]
对应的 [ A , B ] , [ C , D ] , [ E , F ] [A,B], [C,D],[E,F] [A,B],[C,D],[E,F],选择 [ A , F ] , [ C , B ] , [ E , D ] [A,F],[C,B],[E,D] [A,F],[C,B],[E,D] 如此发现,选择的区间一定为某个区间的起点,到对应的最后区间的右端点即可。
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
#define mem(x, y) memset(x, y, sizeof(x))
typedef long long ll;
typedef vector<ll> vll;
const int N = 1e5 + 7;
ll a[N];
vll L, R;
void solve() {
mem(a, 0);
L.clear(), R.clear();
int n, m, l, r;
cin >> n >> m;
while (m--) {
cin >> l >> r;
if (l > r)
a[l]++, a[n + 1]--, a[1]++, a[r + 1]--;
else
a[l]++, a[r + 1]--;
}
// 合并重合区间
rep(i, 1, n) a[i] = a[i - 1] + a[i];
rep(i, 1, n) {
if (a[i - 1] <= 0 and a[i] > 0)
L.emplace_back(i);
if (a[i] > 0 and a[i + 1] <= 0)
R.emplace_back(i);
}
int len = L.size();
cout << len << endl;
rep(i, 0, len - 1) cout << L[i] << ' ' << R[(len - 1 + i) % len] << endl;
}
signed main() {
int t;
cin >> t;
while (t--)
solve();
return 0;
}