目录
一:概念定义
合并所有有交集的区间。例如【2,4】和【3,7】,取其并集得到【2,7】为最终结果
画个图帮助理解
二:题目描述
给定 n 个区间 [,l,r],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
例如:[1,3] 和 [2,6] 可以合并为一个区间 [1,6]。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含两个整数 l 和 r。
输出格式
共一行,包含一个整数,表示合并区间完成后的区间个数。
数据范围
1 ≤ n ≤ 100000,
−10^9 ≤ l ≤ r ≤ 10^9
输入样例
5
1 2
2 4
5 6
7 8
7 9
输出样例
3
三:思路解析
首先,题目会输入很多的区间,区间的左右端点杂乱无章,如果要合并只能用暴力的方式,但是暴力显然过不了所有数据。因此,容易联想到根据左端点从小到大排序,排序完成之后,正在维护的区间和该区间右侧的区间只有3种情况,如下图:
对第一种情况:正在维护的区间的左右端点都不用改变,因为求并集之后还是原区间
对第二种情况:正在维护的区间的右端点小于右侧区间的右端点且两个区间有交集,因此要更新右端点
对第三种情况:正在维护的区间和右侧区间没有交集,所以更新答案res++,且将右侧区间作为下一轮需要维护的区间
用到的结构:由于输入依然是成对出现,因此还是考虑用pair结构存储数据,另外,对pair排序时,会默认先对第一个关键字排序。
四:万年无误代码模板
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std ;
typedef pair<int,int> PII ;
vector<PII> nums,res ;
int main()
{
int st=-2e9,ed=-2e9 ; //ed代表区间结尾,st代表区间开头
int n ;
scanf("%d",&n) ;
while(n--)
{
int l,r ;
scanf("%d%d",&l,&r) ;
nums.push_back({l,r}) ;
}
sort(nums.begin(),nums.end()) ;//按左端点排序
for(auto num:nums) //遍历所有输入
{
if(ed<num.first) //对应思路解析的情况3:两个区间无法合并
{
if(ed!=-2e9) res.push_back({st,ed}) ; //只要不是初始状态的无限区间,就可以放入答案数组
st=num.first,ed=num.second ; //更新区间
}
//对应思路解析的情况2:两个区间可以合并,且区间1不包含区间2,区间2不包含区间1
else if(ed<num.second)
ed=num.second ; //更细右端点,合并两个区间
}
//(实际上也有思路解析的情况1:区间1包含区间2,此时不需要任何操作,可以省略)
//注:排过序之后,右侧区间不可能包含被维护的区间
res.push_back({st,ed});
//考虑循环结束时的st,ed变量,此时的st,ed变量不需要继续维护,它的后面没有区间了,所以无法进去第一个if内部放入res中,
//因此只需要放进res数组即可。
printf("%d",res.size()) ;
return 0 ;
}
创作不易,建议点赞+收藏+关注,以免找不到宝贝文章了。
基础集训结束后将开展拔高系列