P1668 [USACO04DEC] Cleaning Shifts S

一天有 T(1 ≤ T ≤ 106) 个时段。约翰正打算安排他的 N(1 ≤ N ≤ 2.5 × 104) 只奶牛来值班,打扫打扫牛棚卫生。每只奶牛都有自己的空闲时间段 $ S_i,E_i$,只能把空闲的奶牛安排出来值班。而且,每个时间段必需有奶牛在值班。

那么,最少需要动用多少奶牛参与值班呢?如果没有办法安排出合理的方案,就输出 −1

输入格式

1 行:NT

2N + 1 行:SiEi

输出格式

一行,输出最少安排的奶牛数。

输入输出样例 #1

输入 #1

1
2
3
4
3 10
1 7
3 6
6 10

输出 #1

1
2

说明/提示

1 ≤ T ≤ 106N ≤ 2.5 × 1041 ≤ Si ≤ Ei ≤ T

Update On 2023/08/08:添加了一组hack数据,详情见这里。叉掉了时间复杂度为 𝒪(nt) 的错解。

分析

很明显,这是一个区间覆盖问题。 直接贪心,每次选择覆盖最长的奶牛。 上代码(O(T)

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
dist: dict[int, int] = {}

n, t= map(int, input().split())

for _ in range(n):
a, b = map(int, input().split())
dist[a] = max(dist.get(a, a), b)

# import json
# print(json.dumps(dist, indent=2))

end = 0
route = 0
now = 0
used = 0
while now <= end+1 and now <=t:
if now in dist:
route = max(route, dist[now])
# print(f'{now=} {route=}')
if now == end+1 and end < route:
end = route
# print(f'{now=} {end=}')
used += 1
# print(f'{now=} {used=}')
now += 1

if end < t:
print(-1)
else:
print(used)

(有意可利用字典优化,或改写为C++,可进一步使用STLmap