题目
有一个局部互联区域内的 **n** 台设备,每台设备都有一定数量的空闲资源,这些资源可以池化共享。用户会发起两种操作:
1. **申请资源**:输入 `1 x`,表示本次申请需要 **x** 个资源。系统要返回当前资源池中能满足此申请且剩余资源最少的设备 **ID**;如果有多台设备满足条件,返回设备 ID 最小的;如果没有任何设备能满足,返回 `0` 并不做任何分配。
2. **释放资源**:输入 `2 y`,表示将第 **y** 次申请(不一定是成功分配的那一次)释放回原设备。释放时,资源立即归还,且空闲资源自动连续,无需考虑空洞。
给定 **n**(1 ≤ n ≤ 1000)、操作次数 **m**(1 ≤ m ≤ 10<sup>5</sup>),以及初始时每台设备的空闲资源数 **d₁…dₙ**(1 ≤ dᵢ ≤ 1000),以及接下来 **m** 行操作,输出每次 “申请” 操作的返回值。
---
思路
1. **维护数组**
- 用 `free[1…n]` 记录每台设备当前的空闲资源数。
- 用 `alloc_dev[i]`、`alloc_amt[i]` 记录第 i 次申请操作实际分配到的设备 ID 和数量,方便后续释放时准确归还。
2. **处理申请**
- 遍历所有设备,挑选出 `free[j] ≥ x` 且 `free[j] - x` 最小的那台;若有并列则取 `j` 最小。
- 如果找到,则 `free[j] -= x`,并在 `alloc_dev`/`alloc_amt` 中记录下来;否则记为分配到 `0`、`0`。
3. **处理释放**
- 给出参数 `y`,直接取出 `alloc_dev[y]` 和 `alloc_amt[y]`,若 `alloc_dev[y] ≠ 0`,则做 `free[ alloc_dev[y] ] += alloc_amt[y]`。
4. **复杂度**
- 每次申请最坏需要 O(n) 扫描,m 次操作中申请操作最多 m 次,总体 O(m·n)。在 n≤1000、m≤10⁵ 的情况下可行。
---
# 代码```python
import sys
def main():
data = sys.stdin.read().split()
it = iter(data)
n = int(next(it)) # 设备数量
m = int(next(it)) # 操作总数
# free[i] 表示设备 i 当前的空闲资源数(1-indexed)
free = [0] + [int(next(it)) for _ in range(n)]
# alloc_dev[i]、alloc_amt[i] 记录第 i 次申请分配到的设备号和资源数
alloc_dev = [0] # 索引从 1 开始,0 号位置不用
alloc_amt = [0]
results = [] # 存放每次申请操作的返回结果
req_cnt = 0 # 已处理的“申请”操作次数,用于记录索引
for _ in range(m):
typ = next(it)
if typ == '1':
# 申请操作
x = int(next(it))
req_cnt += 1
best_dev = 0 # 最优设备 ID
best_rem = 10**18 # 最优剩余资源(越小越好)
# 在所有设备中找到能满足且剩余最少的
for dev in range(1, n+1):
if free[dev] >= x:
rem = free[dev] - x
# 更新最优:剩余更少或并列时 ID 更小
if rem < best_rem or (rem == best_rem and (best_dev == 0 or dev < best_dev)):
best_rem = rem
best_dev = dev
if best_dev:
# 能分配,更新空闲资源并记录
free[best_dev] -= x
alloc_dev.append(best_dev)
alloc_amt.append(x)
else:
# 分配失败,记为 0
alloc_dev.append(0)
alloc_amt.append(0)
results.append(str(best_dev))
else:
# 释放操作
y = int(next(it)) # 第 y 次申请
dev = alloc_dev[y] # 取出当时分配的设备
amt = alloc_amt[y] # 取出当时分配的数量
if dev != 0:
# 恢复资源
free[dev] += amt
# 输出所有申请操作的返回值
sys.stdout.write(" ".join(results))
if __name__ == "__main__":
main()