还是贪心法。把原始数据排序,排序的规则是先按照右端点排序,右端点相同的情况下,再按照左端点排序。然后最左边开始遍历线段,取第一个线段的右端点,判断是否和第二个线段的右端点相等,如果相等,肯定可以缩短为两个相邻的;如果不想等,再判断第一个右端点是否小于第二个左端点,如果小于,则中间肯定有空隙,标记加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;
}