区间选点
给定N个闭区间[ai,bi],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。
输出选择的点的最小数量。
位于区间端点上的点也算作区间内。
输入格式
第一行包含整数N,表示区间数。
接下来N行,每行包含两个整数ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示所需的点的最小数量。
数据范围
1≤N≤10^5,
−10^9≤ai≤bi≤10^9
输入样例
3
-1 1
2 4
3 5
输出样例
2
代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<pair<int, int>>loc;
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
int l, r;
scanf("%d%d", &l, &r);
loc.push_back({ r,l });
}
sort(loc.begin(), loc.end());//按右端点排序
int st = -2e9, ed = -2e9;
int res = 0;
for (auto it : loc)//遍历数组
{
if (ed < it.second)//区间没有交集
{
res++;//选取的点加一
ed = it.first;//更新点的坐标
}
}
printf("%d", res);
return 0;
}
区间分组
给定N个闭区间[ai,bi],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。
输出最小组数。
输入格式
第一行包含整数N,表示区间数。
接下来N行,每行包含两个整数ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示最小组数。
数据范围
1≤N≤10^5,
−10^9≤ai≤bi≤10^9
输入样例
3
-1 1
2 4
3 5
输出样例
2
代码
#include<iostream>
#include<algorithm>
#include<queue>
#include<stdio.h>
using namespace std;
typedef long long LL;
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 t = range[i];
if (heap.empty() || heap.top() >= t.l)//队列为空或区间的左端点小于等于小根堆的根
heap.push(t.r);
else
{
heap.pop();//删去小根堆的根
heap.push(t.r);//更新小根堆的根
}
}
printf("%d", heap.size());
return 0;
}
区间覆盖
给定N个闭区间[ai,bi]以及一个线段区间[s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。
输出最少区间数,如果无法完全覆盖则输出-1。
输入格式
第一行包含两个整数s和t,表示给定线段区间的两个端点。
第二行包含整数N,表示给定区间数。
接下来N行,每行包含两个整数ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示所需最少区间数。
如果无解,则输出-1。
数据范围
1≤N≤10^5,
−10^9≤ai≤bi≤10^9,
−10^9≤s≤t≤10^9
输入样例
1 5
3
-1 3
2 4
3 5
输出样例
2
代码
#include<iostream>
#include<algorithm>
#include<queue>
#include<stdio.h>
using namespace std;
typedef long long LL;
const int N = 1e5+10;
int st, ed;//目标区间
int n;
struct Range
{
int l, r;
bool operator<(const Range& W)const//重载小于号,按左端点排序
{
return l < W.l;
}
}range[N];
int main()
{
cin >> st >> ed >> 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 falg = false;//判断是否完全覆盖
for (int i = 0; i < n; i++)
{
int j = i, r = -2e9;
while (j < n && range[j].l <= st)//寻找覆盖st并且右端点最大的区间
{
r = max(r, range[j].r);
j++;
}
res++;
if (r < st)//无法覆盖
{
res = -1;
break;
}
if (r >= ed)//已经完全覆盖
{
falg = true;
break;
}
st = r;//覆盖区间而不是整点
i = j - 1;//前面满足条件后j 加了1
}
if (falg == false)
printf("-1");
else
printf("%d", res);
return 0;
}
最大不相交区间数量
给定N个闭区间[ai,bi],请你在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点)。
输出可选取区间的最大数量。
输入格式
第一行包含整数N,表示区间数。
接下来N行,每行包含两个整数ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示可选取区间的最大数量。
数据范围
1≤N≤10^5,
−10^9≤ai≤bi≤10^9
输入样例
3
-1 1
2 4
3 5
输出样例
2
代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<pair<int, int>>loc;
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
int l, r;
scanf("%d%d", &l, &r);
loc.push_back({ r,l });
}
sort(loc.begin(), loc.end());//按右端点排序
int st = -2e9, ed = -2e9;
int res = 0;
for (auto it : loc)//遍历数组
{
if (ed < it.second)//区间没有交集
{
res++;//选取的点加一
ed = it.first;//更新点的坐标
}
}
printf("%d", res);
return 0;
}