题目描述
给定 n 个区间 [li,ri],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
例如:[1,3]和[2,6]可以合并为一个区间[1,6]。
提示:以下是本篇文章正文内容,下面案例可供参考
一、主要思想
总体上,有点像是贪心算法,先把一个问题分解成多个问题,然后在局部求得最优的解,局部求得的最优解就是整体解中的一个。
在这里实际上就是,先要对输入的各个区间,按照其左端点的值进行排序,然后维护一个区间,这个区间首先让它是,左端点最小的区间,然后接下来,对各区间进行扫描,在扫描的过程中,会遇到3种情况,对于每一种情况,我们需要进行不同的处理。下面是3中情况的具体处理方式:
- 维护的区间,包括扫描到的区间,这个时候,维护的区间不需要变,继续进行下一个扫描。
- 维护的区间,交于扫描到的区间,这个时候,更新维护的区间的右端点,维护区间的右端点等于扫描到的区间的右端点,进行下一步。
- 维护的区间,相离于扫描到的区间,即维护的区间和扫描到的区间没有交集,这个时候更新维护的区间的左右端点为扫描到的区间,这个时候我们已经知道,我们已经成功合并了一个区间,然后结果加一,进行下一个扫描,直到扫描结束。
二、代码实现
#include<bits/stdc++.h>
using namespace std;
//1.按照区间左端点排序,
//2.维护一个当前区间,扫描整个区间,合并有交集的区间.
typedef pair<int, int> PII;
const int N=100010;
int n;
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=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;
}