这是一道区间覆盖去重的计数问题,核心是计算施工区域(可能重叠)总共移除的树的数量,再用初始总树数减去该数量得到剩余树数。
解题思路一:集合法
- 初始树数计算:马路长度为
L,从0到L的每个整数点都有树,因此初始总树数为L + 1。 - 标记移除区域:用集合(自动去重)记录所有施工区域覆盖的位置,避免重复统计重叠区域的树。
- 计算剩余树数:初始总树数减去被移除位置的数量,得到最终剩余树数。
代码实现
# 读取马路长度L和施工区域数M
L, M = map(int, input().split())
# 用集合存储被移除的树的位置(自动去重)
removed = set()
# 遍历每个施工区域,标记移除的位置
for _ in range(M):
l, r = map(int, input().split())
# 将区间[l, r]内的所有位置加入集合
for pos in range(l, r + 1):
removed.add(pos)
# 初始总树数 - 被移除的树数 = 剩余树数
remaining = (L + 1) - len(removed)
print(remaining)
解题思路二:数组法
思路分析
- 初始化数组:创建一个长度为
L + 1的数组trees,并将所有元素初始化为0。这个数组的每个下标i代表马路上位置为i的那棵树。0表示这棵树没有被移除。 - 标记施工区域:遍历每一个施工区域
[l, r]。对于这个区间内的每一个位置i(从l到r),我们将数组trees中对应的元素trees[i]的值加1。这表示位置i的树被移除了(加1可以表示被覆盖了一次,即使多个区域重叠,值会大于1,但我们只关心它是否被覆盖过)。 - 统计剩余树木:最后,遍历整个
trees数组,统计值为0的元素的个数。这个个数就是没有被任何施工区域覆盖的树的数量,也就是题目要求的答案。
代码实现(Python)
# 读取马路长度 L 和施工区域数 M
L, M = map(int, input().split())
# 1. 初始化数组,长度为 L+1,所有元素为 0
# trees[i] = 0 表示位置 i 的树未被移除
trees = [0] * (L + 1)
# 2. 标记施工区域
for _ in range(M):
l, r = map(int, input().split())
# 遍历区间 [l, r] 内的每一个位置
for i in range(l, r + 1):
# 将该位置标记为被移除(加 1)
trees[i] += 1
# 3. 统计剩余的树的数量(即数组中值为 0 的元素个数)
remaining_trees = 0
for is_removed in trees:
if is_removed == 0:
remaining_trees += 1
print(remaining_trees)
方法对比与思考
| 特性 | 集合(Set)方法 | 数组(Array)方法 |
|---|---|---|
| 核心思想 | 记录所有被移除的位置 | 标记每个位置是否被移除 |
| 内存占用 | 与被移除的位置数量成正比。如果施工区域小,内存效率高。 | 与马路总长度 L 成正比。无论施工区域大小,都需要 L+1 个空间。 |
| 时间效率 | 主要耗时在 for pos in range(l, r + 1): removed.add(pos),时间复杂度为 O(总覆盖长度)。 |
主要耗时在 for i in range(l, r + 1): trees[i] += 1,时间复杂度同样为 O(总覆盖长度)。 |
| 代码简洁性 | 相对更简洁,利用了集合的自动去重特性。 | 也很直观,代码逻辑清晰。 |



京公网安备 11010502036488号