算法学习笔记(51)——区间问题
区间问题
区间选点
题目描述
给定 个闭区间 ,请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。
输出选择的点的最小数量。
位于区间端点上的点也算作区间内。
输入格式
第一行包含整数 ,表示区间数。
接下来 行,每行包含两个整数 ,表示一个区间的两个端点。
输出格式
输出一个整数,表示所需的点的最小数量。
数据范围
输入样例:
3
-1 1
2 4
3 5
输出样例:
2
算法思路:
- 将每个区间按照右端点从小到大排序
- 从前往后依次枚举每一个区间
- 如果当前区间已经包含点,则直接pass
- 否则选择当前区间的右端点
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
struct Range
{
int l, r;
// 重载小于操作符,按照区间右端点排序
bool operator< (const Range &w) const {
return r < w.r;
}
}range[N];
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ ) {
int l, r;
cin >> l >> r;
range[i] = {l, r};
}
sort(range, range + n);
int res = 0, ed = -2e9;
for (int i = 0; i < n; i ++ )
if (range[i].l > ed) {
res ++;
ed = range[i].r;
}
cout << res << endl;
return 0;
}
最大不相交区间数量
题目描述
给定 个闭区间 ,请你在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点)。
输出可选取区间的最大数量。
输入格式
第一行包含整数 ,表示区间数。
接下来 行,每行包含两个整数 ,表示一个区间的两个端点。
输出格式
输出一个整数,表示可选取区间的最大数量。
数据范围
输入样例:
3
-1 1
2 4
3 5
输出样例:
2
与上一题思路及代码完全相同。
区间分组
题目描述
给定 个闭区间 ,请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。
输出最小组数。
输入格式
第一行包含整数 ,表示区间数。
接下来 行,每行包含两个整数 ,表示一个区间的两个端点。
输出格式
输出一个整数,表示最小组数。
数据范围
输入样例:
3
-1 1
2 4
3 5
输出样例:
2
算法思路
- 将所有区间按左端点从小到大排序
- 从前往后处理每个区间
- 判断能否将其放到某个现有的组中(判断当前区间的左端点是否小于某个现有的组的右端点)
- 如果不存在这样的组,则开新组,然后再将其放进去
- 如果存在这样的组,将其放进去,并更新当前组的
Max_r
- 判断能否将其放到某个现有的组中(判断当前区间的左端点是否小于某个现有的组的右端点)
可以利用小根堆来动态维护最小的Max_r
。
#include <iostream>
#include <algorithm>
#include <queue>
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()
{
cin >> n;
for (int i = 0 ; i < n; i ++ ) {
int l, r;
cin >> 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 {
int t = heap.top();
heap.pop();
heap.push(r.r);
}
}
cout << heap.size() << endl;
return 0;
}
区间覆盖
题目描述
给定 个闭区间 以及一个线段区间 ,请你选择尽量少的区间,将指定线段区间完全覆盖。
输出最少区间数,如果无法完全覆盖则输出 。
输入格式
第一行包含两个整数 和 ,表示给定线段区间的两个端点。
第二行包含整数 ,表示给定区间数。
接下来 行,每行包含两个整数 ,表示一个区间的两个端点。
输出格式
输出一个整数,表示所需最少区间数。
如果无解,则输出 。
数据范围
输入样例:
1 5
3
-1 3
2 4
3 5
输出样例:
2
算法思路
- 将所有区间按照左端点从小到大排序
- 从前往后依次枚举每个区间,在所有能覆盖
start
的区间中,选择右端点最大的区间,然后将start
更新成右端点的最大值
#include <iostream>
#include <algorithm>
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()
{
int st, ed;
cin >> st >> ed;
cin >> n;
for (int i = 0; i < n; i ++ ) {
int l, r;
cin >> 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;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】