803. 区间合并
文章目录
- 题目描述
- 输入格式:
- 输出格式:
- 数据范围
- 输入样例
- 输出样例
- 方法:区间合并
- 解题思路
- 代码
- 复杂度分析:
题目描述
给定 n n n 个区间 [ l i , r i ] [l_i,r_i] [li,ri],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
例如:[1,3] 和 [2,6] 可以合并为一个区间 [1,6]。
输入格式:
第一行包含整数 n。
接下来 n 行,每行包含两个整数 l 和 r。
输出格式:
共一行,包含一个整数,表示合并区间完成后的区间个数。
数据范围
- 1 ≤ N ≤ 100000 1≤N≤100000 1≤N≤100000
- − 1 0 9 ≤ l i ≤ r i ≤ 1 0 9 -10^9≤l_i≤r_i≤10^9 −109≤li≤ri≤109
输入样例
5
1 2
2 4
5 6
7 8
7 9
输出样例
3
方法:区间合并
解题思路
- 按区间的左端点进行从小到大的排序
- 我们把维护区间的左端点记为指针 st,右端点记为指针 ed
每次搜索一个新的区间,它与维护区间之间有 3 种情况:
- 新区间是维护区间的子区间
- 新区间与维护区间有相交部分
- 新区间与维护区间没有相交部分
依据新区间和维护区间是否有相交的部分,可以将上述 3 种情况视为 2 种情形。
如果新区间的左端点 > 维护区间的右端点,则两个区间没有相交部分,则将维护区间的左右端点保存起来;
如果新区间的左端点 <= 维护区间的右端点,则两个区间有相交部分,则更新维护区间的右端点,取两个区间右端点的最大值。
Tips
- sort 在 c++ 中,会优先对左端点进行从小到大的排序,再对右端点进行从小到大的排序。
- 将 vector 容器作为函数参数,使用引用传递的方式,在形式参数前加上 &,函数内部形参发生变化时,这种改变可以直接传递给被调用的实参。
- 注意 st != -2e9,把 -2e9 换成再小一点的数就会报错,有哪位大佬懂得可以告诉我吗?
代码
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int,int> PII;
vector<PII> segs;
int n;
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(seg.second, ed);
}
if(st != -2e9) res.push_back({st, ed});
segs = res;
}
int main() {
cin >> n;
while(n--) {
int l, r;
cin >> l >> r;
segs.push_back({l, r});
}
merge(segs);
cout << segs.size();
return 0;
}
复杂度分析:
- 时间复杂度: O ( n × l o g 2 n ) O(n\times log_2n) O(n×log2n)
- 空间复杂度: O ( n ) O(n) O(n)