小e很喜欢看少儿频道,现在有n个动画片,第i个动画片每天以固定 [ l i , r i ] [l_i, r_i] [li,ri]的时间在全网播出,因为有很多电视台都在播出,所以时间可能重叠。
小e如果看一部动画片,就会从头看到尾,然后再去看另外一部。
也就是说,只要小e从 l i l_i li看到 r i r_i ri就算是看完了第i部动画片,换台不需要时间(中途不允许换台,在两端点位置允许换台)。
请问小e最多完整的看完多少个动画片?
注意,可能存在某些动画片一开始就结束( l i = r i l_i = r_i li=ri),此时小e只需疯狂快速换台即可看完。
第一行一个整数n,表示动画片的个数。 ( 1 ≤ n ≤ 2 × 1 0 5 ) (1 \leq n \leq 2 \times 10^5) (1≤n≤2×105)
接下来n行,每行两个整数表示 l i , r i l_i, r_i li,ri。 ( 1 ≤ l i ≤ r i ≤ 1 0 9 ) (1 \leq l_i \leq r_i \leq 10^9) (1≤li≤ri≤109)
一个整数表示答案。
5
1 4
5 6
7 9
3 6
8 10
3
解释: 可以选择看完第1, 2, 5这三部动画片。
贪心算法,在给定的多个区间中选择尽可能多的不重叠区间。
首先,代码定义了一个全局变量n
和ans
,以及一个存储pair
类型的向量v1
。n
用于存储区间的数量,ans
用于存储结果,v1
用于存储所有的区间。
在main
函数中,首先读取区间的数量n
,然后读取每一个区间的左右端点,并将它们以pair
的形式存储在v1
中。
接着,对v1
进行排序,排序规则是先按照区间的右端点升序排序,如果右端点相同,那么再按照左端点升序排序。这是因为我们希望尽可能选择右端点小的区间,这样后面的空间就更大,可以选择更多的区间。
然后,遍历排序后的v1
,对于每一个区间,如果它的左端点不小于当前的右端点pr
,那么就选择这个区间,更新pr
为这个区间的右端点,并将结果ans
加1。否则,就跳过这个区间。
最后,输出结果ans
,即最多可以选择的不重叠区间的数量。
#include
#include
#include
#define mp make_pair
#define ll long long
#define AUTHOR "HEX9CF"
using namespace std;
int n;
ll ans;
vector<pair<int, int>> v1;
bool cmp(pair<int, int> x, pair<int, int> y) {
if (x.second == y.second) {
return x.first < y.first;
}
return x.second < y.second;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
int l, r;
cin >> l >> r;
v1.push_back(mp(l, r));
}
sort(v1.begin(), v1.end(), cmp);
ans = 0;
auto it1 = v1.begin();
int pr = 1;
for (; it1 != v1.end(); it1++) {
if (it1->first < pr) {
continue;
}
pr = it1->second;
ans++;
// cout << it1->first << " " << it1->second << " " << pr << endl;
}
cout << ans << endl;
return 0;
}