一、区间和并算法模板
二、题目
给定 n 个区间[l,r],要求合并所有有交集的区间。注意如果在端点处相交,也算有交集。输出合并完成后的区间个数。例如:[1,3] 和 [2,6] 可以合并为一个区间 [1,6]。
输入格式
第一行包含整数 n。
接下来 n行,每行包含两个整数 l和 r。
输出格式
共一行,包含一个整数,表示合并区间完成后的区间个数。
数据范围
1≤n≤100000,
−≤l≤r≤
输入样例:
5
1 2
2 4
5 6
7 8
7 9
输出样例:
3
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef pair<int, int>PII;
vector<PII>segs;
void merge(vector<PII>& segs)
{
vector<PII>res;
sort(segs.begin(), segs.end());// 对区间进行排序
int st = -2e9, ed = -2e9;// 初始化合并区间的起始和结束点为一个非常小的数
for (auto seg : segs)
{
if (ed < seg.first)// 如果当前区间的结束点小于下一个区间的起始点
{
if (st != -2e9)res.push_back({ st,ed });// 如果 st 不是初始值,说明我们已经有了一个合并区间
st = seg.first, ed = seg.second;// 更新当前合并区间的起始点和结束点
}
else ed = max(ed, seg.second);// 否则,更新当前合并区间的结束点为两个区间结束点的最大值
}
if (st != -2e9)res.push_back({ st,ed }); // 循环结束时,如果 st 不是初始值,说明还有最后一个合并区间需要添加
segs = res;// 用合并后的区间替换原始区间
}
int main()
{
int n;
cin >> n;
while (n--)
{
int l, r;
cin >> l >> r;
segs.push_back({ l,r });
}
merge(segs);
cout << segs.size() << endl;
return 0;
}
三、 疑问分析
注:区间和并的模板中用的是seg.first和seg.second不是segs.
1、请问为什么右端点不是赋值为正无穷?
正无穷就没办法写了,本来就是要判断ed是否小于seg.first,如果ed为正无穷,就一直比seg.first大,最后答案也就恒为1
2、使用 st != -2e9
的原因:
st
和ed
被初始化为-2e9
,这是为了在开始时确保任何区间的起始点都会大于st
,从而触发合并逻辑。- 当
st
的值改变,不再是-2e9
时,这意味着我们已经开始构建一个新的合并区间。 - 在循环中,每次检测到一个区间的结束点小于下一个区间的起始点时,我们认为当前合并区间已经完成,并且将其添加到结果向量
res
中。 - 在添加到
res
之前检查st != -2e9
是为了确保我们只添加有效的合并区间(即那些已经开始构建且不完全是初始值的区间)。 - 如果
st
仍然是-2e9
,那么这意味着我们还没有开始构建任何合并区间,因此没有必要添加它到结果中。
简而言之,st != -2e9
用于检查当前是否已经确定了合并区间的起始点,从而避免添加无效的区间到结果中。确保在处理区间合并问题时,这个值小于任何可能遇到的区间起始点。将 st
和 ed
初始化为一个非常小的数,可以保证在比较过程中,任何区间的起始点都会大于这个初始值。通过设置一个极端的初始值,我们可以很容易地区分一个区间是否已经开始处理(即 st
是否已经被更新为一个实际的区间起始点)。
3、void merge(vector<PII> &segs) 中的vector<PII> &segs是什么意思
void merge(vector<PII> &segs)
是一个 C++ 函数声明,其含义如下:
void
:表示这个函数没有返回值。merge
:是这个函数的名称。vector<PII> &segs
:是这个函数的参数列表,其中定义了一个参数segs
。
参数 segs
的具体含义:
vector<PII>
:表示参数segs
是一个vector
容器,其存储的元素类型是PII
。这里PII
很可能是一个typedef
别名,指向pair<int, int>
或类似的自定义类型。vector
是一个动态数组,可以存储任意数量的PII
类型对象。&segs
:表示segs
是一个引用参数。这意味着函数接收的不是一个vector<PII>
类型的副本,而是对调用时传递的实际对象的引用。因此,merge
函数可以直接修改原始vector
对象。
综合来看,void merge(vector<PII> &segs)
表示定义了一个名为 merge
的函数,它接受一个对 vector<PII>
类型对象的引用作为参数,并且不返回任何值(无返回类型为 void
)。函数的目的可能是对传入的 vector
进行某种操作,例如区间合并,且这些操作的结果会直接反映在传入的 vector
对象上。