P1803 凌乱的yyy / 线段覆盖

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;
		else
			return 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;
}
posted @ 2025-01-09 22:39  IronMan_PZX  阅读(102)  评论(0)    收藏  举报
Title