
差分 + 贪心
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int n;
void solve()
{
cin >> n;
vector<pair<int,int>> s;
for (int i = 0; i < n; i ++) {
int a, b;
cin >> a >> b;
s.push_back({a, 1});
s.push_back({b + 1, -1});
}
sort(s.begin(), s.end());
int res = 0, sum = 0;
for (auto [x, c] : s) {
sum += c;
res = max(res, sum);
}
cout << res << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
solve();
return 0;
}
- 利用差分,找到被最多区间覆盖的一段,这段就是所需的最小区间数目
小根堆 + 贪心
点击查看代码
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 1e5 + 10;
int n;
struct Range {
int l, r;
bool operator < (const Range &W) const {
return l < W.l;
}
}range[N];
int main()
{
cin >> n;
for (int i = 0; i < n; i ++) {
int l, r;
scanf("%d %d", &l, &r);
range[i] = {l, r};
}
sort(range, range + n);
priority_queue<int, vector<int>, greater<int>> heap;
for (int i = 0; i < n; i ++) {
auto r = range[i];
if (heap.empty() || heap.top() >= r.l) heap.push(r.r);
else {
heap.pop();
heap.push(r.r);
}
}
cout << heap.size() << endl;
return 0;
}
- 算法思想
① 将所有区间按左端点从小到大排序
② 从前往后处理每个区间
判断是否将其放到放到某个现有的组中 $ L[i] \geqslant max(r) $
如果不存在这样的组,则开新组,然后再将其放进去
如果存在这样的组,将其放进去,并更新当前组的 $ max(r) $
(使用小根堆维护右端点最小值,每次只需判断当前区间左端点和小根堆最小值的关系,更新时,把小根堆最小值进行更新)
- 算法的最优性解释
设最优解是 \(ans\) ,一种可行解是 \(cnt\)
① 最优解要保证组数最小,即 \(ans \leqslant cnt\)
② 根据算法思路,在选第 \(cnt\) 个组时,前 \(cnt - 1\) 个组的区间都与第 \(cnt\) 个组的区间有交集,也就是说,至少需要 \(cnt\) 个组,才能保证区间没有交集,\(ans \geqslant cnt\)
综上, \(ans = cnt\) ,最优性得证