区间合并
区间合并,顾名思义,就是将一系列能合并的区间合并
核心代码
void merge(vector<PII>&segs)
{
int st = 2e9, ed = -2e9;
vector<PII> res;
sort(segs.begin(), segs.end());
//注意,(st, ed)的更新顺序相比于(i.first, i.second)是落后的
for (auto i : segs)
{
if (ed < i.first)
{
if (st != 2e9) res.push_back({st, ed});
st = i.first, ed = i.second;
}
else ed = max (ed, i.second);
}
if (st != 2e9) //这里是为了防止出现参数为空的情况
res.push_back({st, ed});
segs = res;
}
例题- 救生员
题目链接:https://www.acwing.com/problem/content/1752/
代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef pair<int, int>PII;
vector<PII> segs;
int n;
int merge(vector<PII>& segs)//引用, 一方面是为了提高速度,还能增加程序的耦合度
{
int res = 0;
sort(segs.begin(), segs.end());
/*
核心思想:从头到尾,分别枚举缺少i号点的情况,最后取最大值
*/
for (int i = 0; i < n; i ++ )
{
//注意下面两行要放到外层循环里面,因为我们相当于将“res.push_back({st, ed})"操作换成了,计算缺少i组点的情况下,对应的sum值。
int sum = 0;
int st = 2e9, ed = -2e9;
for (int j = 0; j < n; j ++ )
{
if (i == j) continue;
if (ed < segs[j].first)
{
if (st != 2e9) sum += ed - st;
st = segs[j].first, ed = segs[j].second;
}
else ed = max(ed, segs[j].second);
}
if (st != 2e9) sum += ed - st;
res = max(res, sum);
}
return res;
}
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ )
{
int l, r;
cin >> l >> r;
segs.push_back({l, r});
}
cout << merge(segs) << endl;
return 0;
}
本题虽然简单,但是却体现了区间合并的本质及实现方式,是基于模板题的一种变式。