1、定义
-
把所有,有交集的区间合并
-
图解:
2、实现
-
步骤如下:
-
1、首先按照每个区间左端点排序
-
2、扫描 所有区间,进行区间合并
-
上述第二条,可以理解为:拿出一个区间去跟它后面的所有的区间去进行合并(因为我们先拿出左端点去排序,所以不用害怕后面的区间会小于什么的)。
-
-
图解:
· 代码模板:
//将所有存在交集的区间进行合并
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;
}
3、例题:803. 区间合并 - AcWing题库
-
给定 n个区间 [li ri],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
例如: [1,3] 和 [2,6] 可以合并为一个区间 [1,6]。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含两个整数 l 和 r。
输出格式
共一行,包含一个整数,表示合并区间完成后的区间个数。
数据范围
1≤n≤100000 −10 ^ 9 ≤ li ≤ ri ≤ 10 ^ 9
-
输入样例:
5 1 2 2 4 5 6 7 8 7 9
输出样例:
3
图解:
AC代码(这里给出两种写法):
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<utility>
using namespace std;
typedef pair<int,int> PII;
const int N = 100010;
vector<PII> segs;
int n;
//区间合并
void merge(vector<PII> &segs)
{
vector<PII> res;//用来存储
//按区间的左端点来进行排序,然后再按照第二个排序(pair很像)
sort(segs.begin(),segs.end());
将st(start)和ed(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()
{
cin >> n;
//存入坐标
for(int i=0;i<n;i++)
{
int l,r;
cin >> l >> r;
segs.push_back({l,r});
}
//区间合并
merge(segs);
cout << segs.size() << endl;
return 0;
}
第二种:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
vector<PII> segs;
int n,res;
int main()
{
cin >> n;
for(int i=0;i<n;i++)
{
int l,r;
cin >> l >> r;
segs.push_back({l,r});
}
sort(segs.begin(),segs.end());
int ed = segs[0].second;
for(int i=1;i<n;i++)
{
if(ed < segs[i].first)
{
res++;
ed = segs[i].second;
}
else ed = max(ed,segs[i].second);
}
cout << res + 1 << endl;
return 0;
}