思路:
使用二分:题目中隐含条件:如果不满足,需要找到第一个不满足的订单。
二分法需要满足单调性or有一个界线使前后两部分性质相反。这里的”界线“为:是否满足条件。假设第i天无法满足,则后面的所有天都无法满足,前面的天都可以满足。即此时的i为要求的答案
代码:
1.二分+差分
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, m;
int r[N];
int d[N], s[N], t[N];
int ans;
int a[N], b[N]; // 差分和前缀和数组
bool check(int num) // 判断此订单是否满足条件
{
memset(a, 0, sizeof(a));
for (int i = 1; i <= num; i++)//遍历订单
{ // 差分
a[s[i]] += d[i];
a[t[i] + 1] -= d[i];
}
for (int i = 1; i <= n; i++)//遍历天数
{ // 前缀和
b[i] = b[i - 1] + a[i];
if (b[i] > r[i])
{
return true;
}
}
return false;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> r[i];
}
for (int i = 1; i <= m; i++)
{
cin >> d[i] >> s[i] >> t[i];
}
int l = 1, r1 = m; // 搜索空间:1-m
if (!check(m))
{
cout << 0;
return 0;
}
int mid;
while (l <= r1)
{
mid = (l + r1) / 2;
if (check(mid))
{
ans = mid;
r1 = mid - 1;
}
else
{
l = mid + 1;
}
}
cout << -1 << endl;
cout << ans;
return 0;
}
2.暴力
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, m;
int r[N];
int d, s, t;
int ans;
int day[N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> r[i];
}
for (int i = 1; i <= m; i++)
{
cin >> d >> s >> t;
if (ans == 0)
{
for (int j = s; j <= t; j++) // 遍历每天
{
day[j] += d;
if (r[j] < day[j])
{
ans = i;
break;
}
}
}
}
if (ans == 0)
{
cout << 0;
}
else
{
cout << -1 << endl;
cout << ans;
}
}