贪心 - 区间合并
例题:
给定 n 个区间 [li,ri],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
例如:[1,3]和[2,6]可以合并为一个区间[1,6]。
输入格式
第一行包含整数n。
接下来n行,每行包含两个整数 l 和 r。
输出格式
共一行,包含一个整数,表示合并区间完成后的区间个数。
数 据 范 围 : 1 ≤ n ≤ 100000 , − 1 0 9 ≤ l i ≤ r i ≤ 1 0 9 数据范围:\\ 1≤n≤100000, −10^9≤l_i≤r_i≤10^9 数据范围:1≤n≤100000,−109≤li≤ri≤109
输入样例:
5
1 2
2 4
5 6
7 8
7 9
输出样例:
3
题解:
所
有
区
间
按
左
端
点
排
序
,
第
i
根
线
段
左
端
点
l
i
,
右
端
点
r
i
,
当
前
合
并
区
间
的
左
端
点
s
t
,
右
端
点
e
d
,
共
有
三
种
情
况
:
①
、
r
i
+
1
<
e
d
,
即
当
前
区
间
完
全
包
含
第
i
+
1
根
线
段
,
则
第
i
+
1
根
线
段
合
并
,
区
间
端
点
不
变
。
所有区间按左端点排序,第i根线段左端点l_i,右端点r_i,当前合并区间的左端点st,右端点ed,共有三种情况:\\①、r_{i+1}<ed,即当前区间完全包含第i+1根线段,则第i+1根线段合并,区间端点不变。
所有区间按左端点排序,第i根线段左端点li,右端点ri,当前合并区间的左端点st,右端点ed,共有三种情况:①、ri+1<ed,即当前区间完全包含第i+1根线段,则第i+1根线段合并,区间端点不变。
②
、
l
i
+
1
<
e
d
<
r
i
+
1
,
即
当
前
区
间
部
分
包
含
第
i
+
1
根
线
段
,
同
样
合
并
,
区
间
右
端
点
e
d
=
r
i
+
1
。
②、l_{i+1}<ed<r_{i+1},即当前区间部分包含第i+1根线段,同样合并,区间右端点ed=r_{i+1}。
②、li+1<ed<ri+1,即当前区间部分包含第i+1根线段,同样合并,区间右端点ed=ri+1。
③
、
l
i
+
1
>
e
d
,
与
当
前
区
间
无
交
集
,
那
么
将
第
i
根
线
段
所
在
的
区
间
加
入
数
组
,
s
t
=
l
i
+
1
,
e
d
=
r
i
+
1
,
重
复
前
面
的
操
作
。
③、l_{i+1}>ed,与当前区间无交集,那么将第i根线段所在的区间加入数组,st=l_{i+1},ed=r_{i+1},重复前面的操作。
③、li+1>ed,与当前区间无交集,那么将第i根线段所在的区间加入数组,st=li+1,ed=ri+1,重复前面的操作。
综 上 : ① 、 e d < l i + 1 , 把 当 前 区 间 加 入 数 组 。 ② 、 e d > = l i + 1 , 区 间 拓 宽 , 右 端 点 e d = m a x ( e d , r i + 1 ) 。 需 要 注 意 的 是 , 最 后 一 根 线 段 没 有 下 一 根 线 段 与 其 比 较 , 但 不 能 忘 了 加 入 到 数 组 。 综上:①、ed<l_{i+1},把当前区间加入数组。\\\qquad\ \ \ \ ②、ed>=l_{i+1},区间拓宽,右端点ed=max(ed,r_{i+1})。\\需要注意的是,最后一根线段没有下一根线段与其比较,但不能忘了加入到数组。 综上:①、ed<li+1,把当前区间加入数组。 ②、ed>=li+1,区间拓宽,右端点ed=max(ed,ri+1)。需要注意的是,最后一根线段没有下一根线段与其比较,但不能忘了加入到数组。
代码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#define P pair<int,int>
#define x first
#define y second
using namespace std;
const int N=1e5+10;
int n,l,r;
vector<P> segs;
void merge(vector<P> &segs)
{
vector<P> res;
sort(segs.begin(),segs.end());
int st=segs[0].x,ed=segs[0].y;
for(int i=1;i<segs.size();i++)
{
if(ed<segs[i].x)
{
res.push_back({st,ed});
st=segs[i].x , ed=segs[i].y ;
}
else ed = max(ed,segs[i].y);
}
res.push_back({st,ed}); //最后一根
segs=res;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
scanf("%d%d",&l,&r);
segs.push_back({l,r});
}
merge(segs);
cout<<segs.size()<<endl;
return 0;
}