过了大概一个礼拜,不甘心地打了一场(首场RATED的ERs),C题再次暴露了我压力下思考不够深入的问题,最坏N方的算法显然超时了,不该偷这个懒,还好评测测了出来,虽然说那天晚上机器特别慢延误了15分钟。
题意: 这个题意就看了好久。一共N天,账户内存入最多D元,每天晚上余额会变动,避免某天账户持平而钱数小于0,或者晚上余额变动后余额大于D。每天早上都可以存任意多的钱直到D。
题解: 因为每天早上都能存钱而且能存到D因此不用担心a[I] = 0的日子钱数不够,要担心的是 钱太多超过D。于是乎,先计算前缀和算出不加钱的话每天账户里会有多少钱,用一个变量tmp记录已经加了多少钱。做一个o(n)的循环,先判断当前tmp加上之后最小的前缀和会不会超过D,如果是a[I]=0的点,判断下能不能过,不能的话加上能加的最大的数。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
const LL INF = (LL)1 << 62;
LL n, d;
LL a[100010];
LL s[100010];
LL top[100010];
LL mtop[100010];
LL ck[100010];
int main(){
cin >> n >> d;
for (int i = 1; i <= n; i++){
scanf("%I64d", &a[i]);
if (a[i] == 0) ck[i] = 1;
s[i] = s[i - 1] + a[i];
top[i] = d - s[i];
}
mtop[n + 1] = top[n];
for (int i = n; i >= 1; i--){
mtop[i] = min(mtop[i + 1], top[i]);
}
LL ans = 0; LL tmp = 0;
for (int i = 1; i <= n; i++){
if (s[i] + tmp > d){
printf("-1\n");
return 0;
}
if (ck[i]){
if (s[i] + tmp >= 0) continue;
else{
if (mtop[i] + s[i]>= 0){
tmp = max(tmp, mtop[i]);
ans++;
}
else{
puts("-1");
//system("pause");
return 0;
}
}
}
}
printf("%d\n", ans);
//system("pause");
return 0;
}