1.3.1 挤牛奶
题目考查
区间合并
解题思路
我们将所有挤奶的区间按照左端点从小到大排序, 遍历所有区间.
不妨设当前连续的区间为[L, R], 遍历到的新区间为[l, r]. 此时有两种情况:
情况①: [l, r] 与 [L, R] 有交集. 则我们可以把新区间加入到老区间当中. 由于l >= L, 所以左端点无需更新, 更新右端点, 执行R = max(R, r)
即可.
情况②: [l, r] 与 [L, R] 无交集. 则我们更新最长连续挤奶时间r1, 最长连续无人挤奶时间r2. 其中有: r1 = max(r1, R - L), r2 = max(r2, l - R)
题目细节
- 对于涉及到区间排序的问题, 需要考虑好排序的规则, 是按照左端点排序, 还是右端点.
- 对于涉及到区间求长度的问题, 需要考虑到是否需要 +1, -1.
- 对于遍历求解类问题, 我们需要考虑最后一种合法情况是否统计了. 倘若我们最后一次循环的情况也合法, 但是循环已经终止了, 导致我们少计算一种合法情况.
AC代码
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
int main()
{
vector<pair<int, int>> v;
int n; cin >> n;
rep(i, n) {
int l, r; scanf("%d %d", &l, &r);
v.push_back({ l, r });
}
sort(v.begin(), v.end());
int r1 = 0, r2 = 0; //结果
int L = v.front().first, R = v.front().second; //题目比较毒瘤, 开始时间不是从0开始.
for (auto& [l, r] : v) {
if (l <= R) R = max(R, r);
else {
r2 = max(r2, l - R);
r1 = max(r1, R - L);
L = l, R = r;
}
}
r1 = max(r1, R - L);
cout << r1 << ' ' << r2 << endl;
return 0;
}