还是贪心法。
把原始数据排序,排序的规则是先依照右端点排序,右端点同样的情况下,再依照左端点排序。然后最左边開始遍历线段,取第一个线段的右端点,推断是否和第二个线段的右端点相等。假设相等,肯定能够缩短为两个相邻的。假设不想等。再推断第一个右端点是否小于第二个左端点,假设小于,则中间肯定有空隙,标记加1。然后在拿第二个的右端点和第三个线段继续同理比較;假设大于,则说明第二个的能够紧邻放在第一个的最右边。相当于把第一个线段放大,这里就是贪心的思想了。
PS:刚開始写cmp函数不小心写了引用,直接CE了一把。
AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cctype> #include <cstring> #include <string> #include <sstream> #include <vector> #include <set> #include <map> #include <algorithm> #include <stack> #include <queue> #include <bitset> #include <cassert> #include <cmath> #include <functional> using namespace std; typedef pair<int, int> Pair; int n; // 先依照右端点从小到大排序,右端点同样的情况下按左端点排序 bool cmp(Pair A, Pair B) { if (A.second != B.second) { return A.second < B.second; } return A.first < B.first; } int main() { ios::sync_with_stdio(false); int T; cin >> T; while (T--) { cin >> n; vector<Pair> A; int x, y; for (int i = 0; i < n; i++) { cin >> x >> y; A.push_back(Pair(x, y)); } sort(A.begin(), A.end(), cmp); // 贪心求解 int ret = 1, right = A[0].second; for (int i = 1; i < n; i++) { if (right != A[i].second) { if (right < A[i].first) { ret++; right = A[i].second; } else { right++; // 这里就是贪心处理 } } } cout << ret - 1 << endl; } return 0; }