小红的慕斯模具统计
题目描述
- N 种模具(编号 0~N-1)
- M 条使用记录:(模具编号, 使用时间)
- K 个查询:给定起始时间 S,求区间 [S, S+X-1] 内不同模具的数量
解法:离线查询 + 双指针 + 哈希表
核心思路
将 K 个查询按结束时间排序,用滑动窗口维护当前区间内的模具种类数。
算法步骤
- 将 M 条记录按时间排序
- 将 K 个查询按结束时间排序
- 用双指针维护滑动窗口 [L, R]
- 右指针扩展时加入记录,左指针收缩时移除记录
- 用哈希表统计当前窗口内每种模具的出现次数
代码实现
# 输入
n, w, q_num = map(int, input().split()) # n: 模具数, w: 跨度, q_num: 查询数
s = [int(x) for x in input().split()] # 起始时间列表
# 构建查询: (起始, 结束, 索引)
queries = [(s[i], s[i] + w - 1, i) for i in range(q_num)]
queries.sort(key=lambda x: x[1])
# 读取记录: (时间, 模具ID)
record_num = int(input())
records = []
for _ in range(record_num):
id, t = map(int, input().split())
records.append((t, id))
records.sort()
# 双指针滑动窗口
ans = [0] * q_num
l = r = 0
cnt = 0
appear = {} # 模具ID -> 出现次数
for start, end, idx in queries:
# 右指针右移:加入 [start, end] 区间内的记录
while r < record_num and records[r][0] <= end:
id = records[r][1]
appear[id] = appear.get(id, 0) + 1
if appear[id] == 1:
cnt += 1
r += 1
# 左指针右移:移除 start 之前的记录
while l < record_num and records[l][0] < start:
id = records[l][1]
appear[id] -= 1
if appear[id] == 0:
cnt -= 1
l += 1
ans[idx] = cnt
print(' '.join(map(str, ans)))
复杂度分析
排序 | O(M log M + K log K) |
滑动窗口 | O(M + K) |
总时间 | O((M+K) log (M+K)) |
空间 | O(M) |
图解示例
记录 (时间, 模具): [(2,1), (3,2), (4,2), (5,3)] 查询1: [3,4] → 窗口内只有模具2 → ans=1 查询2: [4,5] → 窗口内有模具2,3 → ans=2

京公网安备 11010502036488号