题目和思路均来自AcWing及其视频讲解
这个文章我当作笔记
给定 N 个闭区间 [ai,bi],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。
输出选择的点的最小数量。
读入区间, 将区间按右端点从小到大的排序, 然后从前往后枚举区间
给定 N 个闭区间 [ai,bi],请你在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点)。
输出可选取区间的最大数量。
读入区间, 将区间按右端点从小到大的排序, 然后从前往后枚举区间
#include
#include
using namespace std;
typedef pair<int, int> PII;
const int N = 100010;
int n;
struct Edge {
int l, r;
bool operator< (const Edge & t) const {
return r < t.r;
}
}nums[N];
int main() {
cin >> n;
for (int i = 0; i < n; i++)
scanf("%d%d", &nums[i].l, &nums[i].r);
sort(nums, nums + n);
int cnt = 0;
int ed = -2e9;
for (int i = 0; i < n; i++) {
if (nums[i].l > ed) {
ed = nums[i].r;
cnt ++;
}
}
cout << cnt << endl;
return 0;
}
给定 N 个闭区间 [ai,bi],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。
输出最小组数。
#include
#include
#include
using namespace std;
const int N = 100010;
int n;
struct Range{
int l, r;
bool operator< (const Range &w) const {
return l < w.l;
}
}range[N];
int main() {
scanf("%d", &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>> store; // 维护每个组的最大的右端点
for (int i = 0; i < n; i++) {
auto r = range[i];
if (store.empty() || store.top() >= r.l) store.push(r.r);
else {
int t = store.top();
store.pop();
store.push(r.r);
}
}
cout << store.size();
return 0;
}
给定 N 个闭区间 [ai,bi] 以及一个线段区间 [s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。
输出最少区间数,如果无法完全覆盖则输出 −1。
#include
#include
using namespace std;
const int N = 100010;
int n;
struct Range {
int l, r;
bool operator< (const Range &w) {
return l < w.l;
}
}range[N];
int main() {
int st, ed;
scanf("%d%d", &st, &ed);
scanf("%d", &n);
for (int i = 0; i < n; i++) {
int l, r;
scanf("%d%d", &l, &r);
range[i] = {l, r};
}
sort(range, range + n);
int res = 0;
bool success = false;
for (int i = 0; i < n; i++) {
int j = i, r = -2e9;
while (j < n && range[j].l <= st) {
r = max(r, range[j].r);
j++;
}
if (r < st) {
res = -1;
break;
}
res++;
if (r >= ed) {
success = true;
break;
}
st = r;
i = j - 1;
}
if (!success) res = -1;
cout << res << endl;
}
给定 n 个区间 [li,ri],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
#include
#include
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 100010;
int n;
PII nums[N];
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
scanf("%d%d", &nums[i].x, &nums[i].y);
}
sort(nums, nums + n);
int cnt = 0;
int r = -1e9 - 10;
for (int i = 0; i < n; i++) {
if (nums[i].x > r) {
cnt++;
r = nums[i].y;
} else {
r = max(nums[i].y, r);
}
}
cout << cnt << endl;
return 0;
}