不要把天数看成一个动态的时间,用数组存储某天原本有多少个教室,表示为第i天原有s[i]个教室.
很容易看出来问题有单调性,所以二分订单数求解.
对于每份订单,其将会使第a天到第b天的教室数量均减少c个.故构造一个差分数组sum,使得sum的前缀和表示对应某天教室数量的变化量.则当天剩余的教室数量为s[i]+(sum[i]的前缀和).
一旦发现某天剩余教室数量小于0,说明不符合,可以很容易写出check函数.
注意如果所有的check都返回了真,最后会有l==m+1,即r保持初始值未变且l增长到r.
#include <algorithm> #include <cstdio> #include <cstring> #include <iostream> using namespace std; int n, m, s[1000010]; int sum[1000010]; struct S { int d, s, t; } a[1000010]; bool check(int x) { memset(sum, 0, sizeof(int) * (n + 1)); for (int i = 1; i <= x; i++) { sum[a[i].s] -= a[i].d; sum[a[i].t + 1] += a[i].d; } for (int i = 1; i <= n; i++) { sum[i] += sum[i - 1]; if (sum[i] + s[i] < 0) return false; } return true; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", s + i); for (int i = 1; i <= m; i++) scanf("%d%d%d", &a[i].d, &a[i].s, &a[i].t); int l = 0, r = m + 1; while (l < r) { int mid = l + r + 1 >> 1; if (check(mid)) l = mid; else r = mid - 1; } if (l == m + 1) puts("0"); else printf("-1\n%d\n", l + 1); return 0; }P1083