题目
思路
- 代码不超时:限制在10的8次方以内;线段树能处理的数据上限是10^5
- 二分:具有二段性,第一个订单不满足,后面的订单也不用去考虑
- 差分(前缀和的逆运算):题目的要求是将一个区间整体减去一个数,最终去判断是否存在某个数小于零
- 二分完之后利用差分将前面若干个订单判断一遍,如果前面存在订单小于0,说明不满足
- AcWing 503. 借教室(寒假每日一题) - AcWing
代码
python
n, m = map(int, input().split())
r = [0] + list(map(int, input().split()))
d = [0] * (m+5)
s = [0] * (m+5)
t = [0] * (m+5)
b = []
def check(mid):
b = [0] * (n+5) # 将 b 初始化为与 r 相同长度的列表,并全部填充为 0
for i in range(1, n+1):
b[i] = r[i] - r[i-1] # 差分数组的初始化
for i in range(1, mid+1): # 处理前 mid 个订单
b[s[i]] -= d[i] # 有订单之后,区间的值要减少 d[i]
b[t[i] + 1] += d[i] # 差分的基本操作
for i in range(1, n+1): # 求差分数组的前缀和,相当于求原数组
b[i] += b[i-1]
if b[i] < 0:
return False # 说明订单不能满足
return True
for i in range(1, m+1):
d[i], s[i], t[i] = map(int, input().split())
L, R = 1, m
while L < R:
mid = (L + R) >> 1
if check(mid)==False:
R = mid
else:
L = mid + 1
if check(m) :
print("0")
else :
print("-1")
print(R)