思路
很容易想到暴力的写法,对于一个订单来说,直接从第一天到最后一天都减去d[i]即可,每个订单复杂度为O(n),总的复杂度为O(n*m)明显超时。
可以发现如果前x个订单不符合要求,那么往后一定不符合,这个性质使得我们可以使用二分来求答案。
我们每次二分一个答案,对于当前答案x,我们需要判断前x个订单是否可以符合要求。如果每一个订单都去暴力去减的话,那么依旧会超时。对于区间减法的操作很容易想到用线段树或者树状数组优化。
但是我们对于这个题我们可以发现这个题的查询是在所有的减法操作之后的,所以我们可以用一种更简单的东西去实现,即差分数组 。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e6 + 5;
int n, m, r[MAXN], d[MAXN], s[MAXN], t[MAXN], diff[MAXN];
bool check(int m)
{
memset(diff, 0, sizeof(diff));
for (int i = 0; i < m; i++)
{
diff[s[i]] += d[i];
diff[t[i] + 1] -= d[i];
}
for (int i = 1; i <= n; i++)
{
diff[i] += diff[i - 1];
if (r[i] < diff[i]) return false;
}
return true;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &r[i]);
for (int i = 0; i < m; i++) scanf("%d%d%d", &d[i], &s[i], &t[i]);
int l = 0, r = m;
while (l < r)
{
int m = l + (r - l) / 2;
if (check(m)) l = m + 1;
else r = m;
}
if (l < m) printf("-1\n%d\n", l);
else printf("0\n");
return 0;
}
/*
4 3
2 5 4 3
2 1 3
3 2 4
4 2 4
*/