第一天:二分

题目引入
有n天,第i天有相应的教室数量ai。
有m份订单,订单编号从 1 到 m 逐次递增,订单内容为d,l,r,表示在 第 l 到 r 天,每天都租借d间教室。
计算出哪一份订单最先无法满足,输出其订单编号。

数据范围
0 <= n,m <= 1e6; 0 <= ai,d <= 1e9; 1 <= l,r <= n
输入
n m
a1 a2 a3 ... an
d l r
.........
输出
如果都可以满足,输出0;否则第一行输出-1,第二行输出对应的订单编号(最先无法满足)

示例
输入

4 3
2 5 4 3
2 1 3
3 2 4
4 2 4

输出

-1
2

代码

import sys

sys.setrecursionlimit(1000000)
input = lambda: sys.stdin.readline().strip()
r1 = lambda: int(input())
r2 = lambda: map(int, input().split())
r3 = lambda: [*map(int, input().split())]


def solve():
    n,m = r2()
    a = r3()
    query = [[]for _ in range(m + 1)]
    for i in range(1,m + 1):
        query[i] = r3()

    def check(x):
        diff = [0] * (n + 2)
        for i in range(1,x + 1):
            d,l,r = query[i]
            diff[l] += d
            diff[r + 1] -= d
        s = 0
        for i in range(1,n + 1):
            s += diff[i]
            x = a[i - 1]
            if s > x:
                return False
        return True
    l,r = 0,m

    while l < r:
        mid = l + r + 1 >> 1
        if check(mid):
            l = mid
        else:
            r = mid - 1
    if l == m:
        print(0)
    else:
        print(-1)
        print(l + 1)


if __name__ == "__main__":

    t = 1
    for _ in range(t):
        solve()

模板总结

0001111100000

①寻找最左边的1

while l < r:
    mid = l + r >> 1
    if check(mid):
        r = mid
    else:
        l = mid + 1

②寻找最右边的1

while l < r:
    mid = l + r + 1>> 1
    if check(mid):
        l = mid
    else:
        r = mid - 1
posted @ 2024-02-29 22:11  gebeng  阅读(7)  评论(0)    收藏  举报