【题目链接】
ybt 1236:区间合并
OpenJudge NOI 2.4 7620:区间合并
【题目考点】
1. 贪心
2. 排序
【解题思路】
解法1. 贪心
将所有区间按左端点从小到大排序。
由于区间数量达到
5
∗
1
0
4
5*10^4
5∗104,因此只能用复杂度为
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)的排序方法。
设所有区间合并在一起的总区间为
[
l
m
,
r
m
]
[l_m, r_m]
[lm,rm],排序后第i区间为
[
l
i
,
r
i
]
[l_i, r_i]
[li,ri]。初始情况,下
l
m
=
l
i
,
r
m
=
r
i
l_m=l_i, r_m=r_i
lm=li,rm=ri
顺序取每个区间,假设取到的第i区间为
[
l
i
,
r
i
]
[l_i, r_i]
[li,ri],尝试将取到的区间和前面所有区间构成的总区间
[
l
m
,
r
m
]
[l_m, r_m]
[lm,rm]进行合并
- 如果 l i ≤ r m l_i \le r_m li≤rm,那么二者可以合并,合并后,如果 r i > r m r_i > r_m ri>rm,那么 r m = r i r_m=r_i rm=ri
- 如果 l i > r m l_i > r_m li>rm,那么二者不可以合并。其余的区间的左端点都大于等于 l i l_i li,都无法和前各面区间合并成的区间 [ l m , r m ] [l_m, r_m] [lm,rm]合并,因此最终无法合并成一个闭区间。
重复上述过程,如果最后所有区间都成功合并,就输出 l m l_m lm与 r m r_m rm,否则输出no。
【题解代码】
解法1:贪心
- 写法1:写cmp函数
#include<bits/stdc++.h>
using namespace std;
#define N 50005
struct Pair//表示一个区间
{
int l, r;
}a[N];
bool cmp(Pair a, Pair b)
{
return a.l < b.l;//左端点小的排在前面
}
int main()
{
int n;
Pair pm;//总区间
cin >> n;
for(int i = 1; i <= n; ++i)
cin >> a[i].l >> a[i].r;
sort(a+1, a+1+n, cmp);
pm = a[1];//初始值为第一个区间
for(int i = 2; i <= n; ++i)
{
if(a[i].l <= pm.r)
pm.r = max(a[i].r, pm.r);
else
{
cout << "no";
return 0;
}
}
cout << pm.l << ' ' << pm.r;
return 0;
}
- 写法2:重载小于号运算符
#include<bits/stdc++.h>
using namespace std;
#define N 50005
struct Pair//表示一个区间
{
int l, r;
bool operator < (const Pair &b) const
{
return l < b.l;//左端点小的排在前面
}
}a[N];
int main()
{
int n;
Pair pm;//总区间
cin >> n;
for(int i = 1; i <= n; ++i)
cin >> a[i].l >> a[i].r;
sort(a+1, a+1+n);
pm = a[1];//初始值为第一个区间
for(int i = 2; i <= n; ++i)
{
if(a[i].l <= pm.r)
pm.r = max(a[i].r, pm.r);
else
{
cout << "no";
return 0;
}
}
cout << pm.l << ' ' << pm.r;
return 0;
}