UVA1617 Laptop

​​点击阅读更多查看文章内容

UVA1617 Laptop

题目链接

题意

这里引用紫皮书上的解释

给定n条长度为1的线段,确定它们的起点,使得第i条线段在[ri,di]之间。输入保证ri≤rj,当且仅当di≤dj,且保证有解。输出空隙数目的最小值。

对这个题目有一点疑问,给定的样例中有[1,3]和[0,3]两个区间,假定[1,3]为第i条线段[0,3]为第j条线段,di≤dj,但是ri>dj,不满足题意所述,猜想可能是题目有误(VJ上的题目也是此条件)。

思路

一道蛮简单的贪心题,首先按照左端点小的在前排序,若左端点相等,则对右端点小的在前排序,然后尽量靠右选点,维护最右端的点ri。

不难判断,当前所选线段与前一个有空隙的情况只有当前线段的左端点大于ri。此时必定有空隙,只需对当前尽量靠右选点即可。

当没有空隙时,首先判断是否可以选ri右边的点,此时需满足当前线段的右端点大于ri。如果右端点等于ri则将ri前移一个,将ri位置空出来给当前线段使用(不必考虑ri是否可以前移,因为题目中提到必定有解),此时最右端的点仍是之前ri的值,如果右端点小于ri,则当前线段选的点在ri左边,ri仍不变。

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<iostream>
#include<algorithm>
using namespace std;
struct line
{
int l, r;
line(int a = 0, int b = 0)
{
l = a;
r = b;
}
bool operator <(const line a)
{
if (l == a.l)
return r < a.r;
return l < a.l;
}
};
const int MAXN = 1e5 + 10;
int T, N;
line lines[MAXN];
int main()
{
int ri;
cin >> T;
while (T--)
{
cin >> N;
for (int i = 0; i < N; i++)
{
cin >> lines[i].l >> lines[i].r;
}
sort(lines, lines + N);
ri = lines[0].r;
int cnt = 0;
for (int i = 1; i < N; i++)
{
if (lines[i].l > ri)
{
cnt++;
ri = lines[i].r;
continue;
}
if (lines[i].r > ri)
{
ri++;
continue;
}
}
cout << cnt << endl;
}
}
作者

ShiHaonan

发布于

2021-05-17

更新于

2025-03-13

许可协议

评论