Acwing 803.区间合并
题目描述
给定 $n$ 个区间 [$l_i$,$r_i$],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
例如:[$1$,$3$] 和 [$2$,$6$] 可以合并为一个区间 [$1$,$6$] 。
输入格式
第一行包含整数$n$。
接下来$n$行,每行包含两个整数$l$和$r$。
输出格式
共一行,包含一个整数,表示合并区间完成后的区间个数。
数据范围
$1 ≤ n ≤ 1000001 ≤ n ≤ 100000$,
$−109 ≤ li ≤ ri ≤ 109$
样例
输入样例:
5
1 2
2 4
5 6
7 8
7 9
输出样例:
3
思路提示
可以先按左端点排序,再维护一个区间,与后面一个个区间进行三种情况的比较,存储到数组里去。
C++ 代码
#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) //情况1:两个区间无法合并
{
if(ed!=-2e9) res.push_back({st,ed}) ; //区间1放进res数组
st=num.first,ed=num.second ; //维护区间2
}
//情况2:两个区间可以合并,且区间1不包含区间2,区间2不包含区间1
else if(ed<num.second)
ed=num.second ; //区间合并
}
//(实际上也有情况3:区间1包含区间2,此时不需要任何操作,可以省略)
//注:排过序之后,不可能有区间2包含区间1
res.push_back({st,ed});
//考虑循环结束时的st,ed变量,此时的st,ed变量不需要继续维护,只需要放进res数组即可。
//因为这是最后的一个序列,所以不可能继续进行合并。
/*
for(auto r:res)
printf("%d %d\n",r.first,r.second) ;
puts("") ;
*/
//(把上面的注释去掉,可以在调试时用)
printf("%d",res.size()) ; //输出答案
return 0 ;
}
大佬牛皮!额也来分享下额滴代码叭
%%%
🙇
斯国一
可以
请问佬发的三个百分号代表什么意思哇
%是模,因此是膜拜
谢谢佬w
%%%
Orz
orz orz
写的很好!个人觉得非常容易理解
orz
为啥N 只开了 1e6
不错不错
你更厉害
这里的N是合并前的区间个数,其实根据这道题目的话开到1e5就够了QwQ
为什么a[]要从a[1]开始,为什么不能从a[0]开始
%%%
写的特别好,终于理解了,谢谢!
Orz,我也贡献一下自己的代码
用了结构体!后生可畏
还是这个好理解
超级清晰
为什么要那么排序佬
为了让左边界 l 升序排列
大佬,这个merge函数为啥参数要用引用呀?求解答
加了&才能修改到原始数据segs
%%%orz,大佬注释好详细,赞
int st=-2e9,ed=-2e9 ;
本人比较菜,不懂为什么st,ed不直接取排序后第一个元素的首尾,而要取-2e9
有道理,这样是可以AC的
int
的最小值为$-2147483647$,所以取$-2e9$比较省事,可以代表int
的最小值;还有一些可以代表
int
最小值的数,例如-0x3f3f3f3f
,-1<<30
等笔误,是
-2147483648
(笑)懂了,谢谢你
用st = -1e9 -10 ed = -1e9 - 10也能 AC ,题目中−10^9≤li≤ri≤10^9 ; 所以这里只要是构造一个初始的空区间,能覆盖取值范围即可,以防[-1000000000 -1000000000] 空区间;直接用int st = s[0].first , ed = s[0].second; int st = s[0].first , ed = s[0].second; 这样就用不着特判定空区间
-0x3f3f3f3f好像不是-2147483648
都表示负无穷的意思 没有很大的区别
知道了,-2e9省事才用,谢谢你
题目不是说$l$和$r$都是$-10^9$~$10^9$吗?为什么还能取到-2e9?
分享一下我的代码叭,感觉写的比较简介
简单易懂,分享一下
else if直接写成else有影响吗? 排序后好像不会出现ed>second的情况吧?
会出现的,那样的话ed就不用改变了。写else后面应该写成ed=max(ed,num.second)
有点不明白cpp语法,st和ed这个-2e9是指2×10^-9吗
指的是-2*10^9
代码对我这种蒟蒻来说太难理解了,比如说
for(auto num:nums)
指的是循环变量num
从1
一直到nums
数组的结尾吗?就是依次遍历nums的元素,num就是取出来的元素
好的谢谢dalao
也可以用for(int i=0;i<nums.size(),i++)来实现 然后取值用nums[i].first来取
贴一个结构体代码hh
# 这好像是贪心?
确实是诶
你写的太棒了,逻辑很清晰
鹈鹕户口ing
提供一个我个人认为更优雅的做法,不需要针对最后一个元素或第一个元素特判:
为何没有线段树?
想问一下右端点可以吗
按右端点排序
来个JAVA代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.io.*;
public class Main {
static int N = 100010;
static List[HTML_REMOVED] segs = new ArrayList<>();
static List[HTML_REMOVED] res = new ArrayList<>();
}