首先看到题目,非常像小学奥数题,所以我们可以每天按照阶段的增加来模拟就可以了(至少我但是觉得是这样的)。https://www.luogu.com.cn/record/190219012。
TLE+WA
模拟肯定不行了,于是我再找了一下规律,原来每次增加的高度是一样的(毕竟每天阶段不会变),所以说我们只需要找到:
于是我写好后又信心满满的提交了上去。https://www.luogu.com.cn/record/190239198。
WA
这是为什么呢,让我们观察一下这组数据:
8 3
-1 -2 4
首先按我们的思路遍历一遍看看一次增加多少,这样的结果就是 4 ,那答案就是 0 2 ?
不对,当我们程序进行第二次遍历后就会发现结果是 5 ,只增加了 1 ,原来第一次遍历并没有在结果中增加 -1 和 -2 (高度不可 < 0 ),而第二次却增加了 -1 和 -2 (高度 > 1+2 ,可以吸收),那我们还需要一个值来在第一次循环中来记录如果全部吸收增加的高度也就是不管是否 < 0 。
知道问题就好办了,只需要一直遍历直到能吸收所有复数就行了。
于是我写好后又又信心满满的提交了上去。
https://www.luogu.com.cn/record/190484745
WA
还有问题,仔细想一下有可能我们得到的每次增长的值虽然 ≤ 0,但是在第二次的某个时间却可以达到目标,例如:
2 4
1 -2 -2 1
虽然每天的增加结果是 -2 可遍历两次后仍然可以达到目标,好,那我们只需要再遍历一次判断是否达到目标就可以了。
#include <bits/stdc++.h>
using namespace std;
long long n,k; // n 总数 k 高度
long long now; // 目前高度
long long now_2;
long long z[114514]; // 阶段攀爬高度
long long ans,ans_2,sum_f,maxx_z;
void pd(long long thenum_pd,long long num1,long long num2){if (thenum_pd>=k) {cout <<num1-1 <<" " <<num2-1;exit(0);}return ;}
void did(){cout <<"-1 -1";exit(0);}
int main(){
cin >>k >>n;
for (int i = 1;i <= n;i ++) cin >>z[i];
for (int i = 1;i <= n;i ++){ // 看到每天的进步
now += z[i],now_2 += z[i],sum_f=min(sum_f,sum_f+z[i]);
now_2=max(now_2,0LL); // 最低高度为 0
maxx_z=max(maxx_z,now);
pd(now_2,1,i); // 判断是否提前到达
}
if (now <= 0){
for (int i = 1;i <= n;i ++){ // 再给你一次机会
now += z[i],now_2 += z[i],sum_f=min(sum_f,sum_f+z[i]);
now_2=max(now_2,0LL);
maxx_z=max(maxx_z,now);
pd(now_2,2,i);
}
did(); // 没有进步那还爬什么
}
now_2=0;
while (!(now_2 >= -sum_f)){ // 直到你能吸收所有退步
for (int i = 1;i <= n;i ++){
now_2 += z[i],now_2=max(now_2,0LL); // 正常爬
now_2=max(now_2,0LL); // 最低高度为 0
pd(now_2,1,i); // 判断是否提前到达
}
ans ++; // 前面的也要算上
}
ans_2 = (k-now_2-maxx_z)/now; // 要爬多久
now_2 += ans_2*now; // 加上后面的
while (1){
for (int i = 1;i <= n;i ++){
now_2 += z[i],now_2=max(now_2,0LL); // 正常爬
pd(now_2,ans_2+ans+1,i); // 判断是否到达
}ans_2 ++;}
return 0;
}