P1803 凌乱的yyy / 线段覆盖
题目
现在各大 oj 上有 \(n\) 个比赛,每个比赛的开始、结束的时间点是知道的。
yyy 认为,参加越多的比赛,noip 就能考的越好(假的)。
所以,他想知道他最多能参加几个比赛。
由于 yyy 是蒟蒻,如果要参加一个比赛必须善始善终,而且不能同时参加 \(2\) 个及以上的比赛。
输入
第一行是一个整数 \(n\),接下来 \(n\) 行每行是 \(2\) 个整数 \(a_{i},b_{i}\ (a_{i}<b_{i})\),表示比赛开始、结束的时间。
输出
一个整数最多参加的比赛数目。
样例
输入
3
0 2
2 4
1 3
输出
2
提示
- 对于 \(20\%\) 的数据,\(n \le 10\);
- 对于 \(50\%\) 的数据,\(n \le 10^3\);
- 对于 \(70\%\) 的数据,\(n \le 10^{5}\);
- 对于 \(100\%\) 的数据,\(1\le n \le 10^{6}\),\(0 \le a_{i} < b_{i} \le 10^6\)。
思路
该问题属于“选择不相交的区间问题”。通过分析可以得到,区间越早终止,越对后面的区间“有利”,因此,按右端点大小排序。
容易分析出,最早结束的区间一定要选择,图中 \(1\) 区间一定要选。选择完 \(1\) 区间后,很快发现其余区间构成新的问题,且与 \(1\) 区间相交的线段不能选择。如此一来,贪心策略便得出:选择最多个不相交的区间问题,首先对右端点进行排序,然后依次选择左端点大于前一个已经选择的区间右端点的区间。上图例子中,应该选择 \(1,2,5\) 区间。
代码
#include <bits/stdc++.h>using namespace std;int n, pre, cnt, ed;struct node
{int s, e;
} p[1000010];bool cmp(const node &u, const node &v)
{if (u.e < v.e)return 1;else if (u.e == v.e){if (u.s < v.s)return 1;elsereturn 0;}return 0;
}int main()
{scanf("%d", &n);for (int i = 1; i <= n; i ++ )scanf("%d %d", &p[i].s, &p[i].e);sort(p + 1, p + n + 1, cmp);ed = p[1].e;for (int i = 2; i <= n; i ++ ){if (p[i].s >= ed){ed = p[i].e;cnt ++;}}cout << cnt + 1 << '\n';return 0;
}