描述见题面
思路:直接二分是在第几个订单结束的,最后检验一下二分出来的答案可不可行
检验思路:使用差分,将前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;
}
京公网安备 11010502036488号