区间和并算法

一、区间和并算法模板

二、题目

给定 n 个区间[l,r],要求合并所有有交集的区间。注意如果在端点处相交,也算有交集。输出合并完成后的区间个数。例如:[1,3] 和 [2,6] 可以合并为一个区间 [1,6]。

输入格式

第一行包含整数 n。

接下来 n行,每行包含两个整数 l和 r。

输出格式

共一行,包含一个整数,表示合并区间完成后的区间个数。

数据范围

1≤n≤100000,
10^{9}≤l≤r≤10^{9}

输入样例:
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 用于检查当前是否已经确定了合并区间的起始点,从而避免添加无效的区间到结果中。确保在处理区间合并问题时,这个值小于任何可能遇到的区间起始点。将 sted 初始化为一个非常小的数,可以保证在比较过程中,任何区间的起始点都会大于这个初始值。通过设置一个极端的初始值,我们可以很容易地区分一个区间是否已经开始处理(即 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 对象上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值