题目来源:AcWing 803. 区间合并
一、题目描述
给定 n n n 个区间 [ l i , r i ] [l_i,r_i] [li,ri],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
例如: [ 1 , 3 ] [1,3] [1,3] 和 [ 2 , 6 ] [2,6] [2,6] 可以合并为一个区间 [ 1 , 6 ] [1,6] [1,6]。
输入格式
第一行包含整数
n
n
n。
接下来 n n n 行,每行包含两个整数 l l l 和 r r 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
二、算法思想
区间合并算法可以快速的将有交集的区间进行合并。
- 按照所有区间的左端点对所有区间进行排序;
- 从前往后进行扫描,每次维护一个当前区间,区间左端点记为
s
t
st
st (start),右端点记为
e
d
ed
ed (end)。假设当前扫描到了第
i
i
i 个区间,则第
i
i
i 个区间和当前区间有如下几种关系:
① 这种情况更新完之后当前区间还是 [ s t , e d ] [st, ed] [st,ed],没有发生变化;
② 这种情况更新完后新的 e d ed ed 应当变为 e d i ed_i edi,区间变为 [ s t , e d i ] [st, ed_i] [st,edi] ,当前区间变长;
③ 这种情况第 i i i 个区间与当前区间没有交集,并且以后出现的新的区间都一定与当前区间没有交集。因此将第 i i i 个区间作为当前区间,当前区间更新为 [ s t i , e d i ] [st_i, ed_i] [sti,edi]。
三、代码
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> node;
const int N = 1e5 + 10, INF = -2e9;
int n;
vector<node> segs;
void merge(vector<node>& segs)
{
vector<node> res;
// pair类型在C++中优先排序first
sort(segs.begin(), segs.end());
int st = INF, ed = INF;
for (auto seg : segs)
if (ed < seg.first)
{
// 完全没有交集
if (st != INF) res.push_back({st, ed});
st = seg.first, ed = seg.second;
}
else ed = max(ed, seg.second);
if (st != INF) res.push_back({st, ed});
segs = res;
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
int l, r;
scanf("%d%d", &l, &r);
segs.push_back({l, r});
}
merge(segs);
printf("%d\n", segs.size());
return 0;
}