文章目录
- 什么是区间合并
- 怎么做区间合并
- [AcWing 803. 区间合并](#AcWing 803. 区间合并)
-
- 思路解析
- [my - CODE](#my - CODE)
- [dalao の CODE](#dalao の CODE)
什么是区间合并
区间合并是指给定多个区间,让你将重合的区间合并为一个区间
怎么做区间合并
区间合并类问题大多三个办法:
- 按左端点排序
- 按右端点排序
- 按左右端点双值排序
AcWing 803. 区间合并
题目链接:https://www.acwing.com/activity/content/problem/content/837/
思路解析
- 我们按左端点大小将区间排序,排完序后从每个区间左端点开始遍历,我们会发现有三种情况
B
区间在A
内C
区间有一部分与A
重合D
区间在A
外
- 我们的思路很明了了,通过两个指针:
st
(start),ed
(end) 来标记我们正在维护的A
数组的左右端点,往后遍历,处理三种情况- 如果遇到
B
:左端点不动,右端点也不动 - 如果遇到
C
:左端点不动,右端点更新为C
的右端点,也就是将A,C
区间合并了 - 如果遇到
D
:左右端点更新为D
的左右端点,相当于现在改为维护D
区间
- 如果遇到
my - CODE
cpp
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> pii;
vector<pii> segs; // 存储区间左右端点
int main()
{
int n, l, r;
int ans = 0;
cin >> n;
while (n -- ){
scanf("%d%d", &l, &r);
segs.push_back({l, r});
}
sort(segs.begin(), segs.end()); // 以左端点优先排序
int st = -1e9 - 1, ed = -1e9 - 1; // 一开始的区间初始化为一个不可能的区间
for(auto seg : segs){
if(seg.first <= ed) ed = max(ed, seg.second); // 有重合,右端点取最大
else{ // 无重合,更新维护的区间
ans++;
st = seg.first;
ed = seg.second;
}
}
cout << ans << endl;
}
dalao の CODE
cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<int, int> PII;
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 = seg.first, ed = seg.second;
}
else ed = max(ed, seg.second);
if (st != -2e9) res.push_back({st, ed});
segs = res;
}
int main()
{
int n;
scanf("%d", &n);
vector<PII> segs;
for (int i = 0; i < n; i ++ )
{
int l, r;
scanf("%d%d", &l, &r);
segs.push_back({l, r});
}
merge(segs);
cout << segs.size() << endl;
return 0;
}
作者:yxc
链接:https://www.acwing.com/activity/content/code/content/40108/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- dalao将合并统计区间的过程抽出来单独写了个
merge()
函数,复用性和可读性更强 - 而且将合并后的区间按秩存入了一个
res
空间,对于本题可能没有卵用,但是在其他区间合并问题中可能会用到合并后的区间 - 不愧是dalao啊,orz %%%%%%