描述见题面
思路:直接二分是在第几个订单结束的,最后检验一下二分出来的答案可不可行
检验思路:使用差分,将前k个(k是二分出来的答案)订单的起始,终止位置之间的所有数减去所需的教室数,最后做一遍前缀和,看是否有
哪一天的教室数量小于0,若有小于0的则不能完成订单
代码:

#include <iostream>

using namespace std;

const int N = 1000010;

int a[N];  // 表示每天有多少教室
int b[N];  // 拷贝数组
int n, m;

struct order  // 使用结构体存储每一个订单的信息
{
    int count, start, end;
}order[N];

bool check(int k)
{
    for (int i = 1; i <= n; i ++ ) b[i] = a[i];  // 拷贝差分数组以供每次使用
    for (int i = 1; i <= k; i ++ )
    {
        int l = order[i].start, r = order[i].end, cnt = order[i].count;
        b[l] -= cnt;
        b[r + 1] += cnt;
    }

    long long res = 0;
    for (int i = 1; i <= n; i ++ )
    {
        res += b[i];
        if (res < 0) return false;
    }

    return true;
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
    for (int i = n; i >= 1; i -- ) a[i] -= a[i - 1];
    for (int i = 1; i <= m; i ++ )
    {
        int a1, a2, a3;
        scanf("%d%d%d", &a1, &a2, &a3);
        order[i] = {a1, a2, a3};
    }

    // 二分第几个订单结束
    int l = 0, r = m;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (!check(mid)) r = mid;  // 取不到的话k最多就到当前mid
        else l = mid + 1;  // 能取到的话就更进一步试试
    }

    if (check(l)) puts("0");
    else printf("-1\n%d\n", l);

    return 0;
}