这题其实不难,为啥放在cf div2的E呢?
下文中,每个round对怪物造成的净伤害为sum,一个round中对这个怪物的最大伤害为mx,均为负数
这题主要是有个坑点:可能在一个round中会有一个点,它大于整个round结束之后对怪物造成的净伤害。所以,我们需要找出一个round中最大的伤害的点mx。
比如,样例1中,最大伤害点是-100-200-300=600。
因此,我们可以这样思考:如果一个round开始之前,这个怪物的血量h<=mx,那它就会死在这个round,而前面我们需要做的,就是把这个怪物的血线压到mx以下,因此,前面造成的伤害为h+mx(mx为伤害,为负数),而这个伤害只能由净伤害造成,因此,需要的round数为need_r=ceil((h+mx)/(-sum)),也就是说,need_r+1轮内这个怪物必死,然后,再遍历di,找出这个怪物会死在哪个点i,就可以得到答案为need_r*n+i.
注意特判情况,也就是在mx和sum均小于怪物血量h的时候,这个怪物无法被杀死。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=2e5+100; template<typename T> void read(T&x){ char ch=getchar(); ll f=1; while(!isdigit(ch)){ if(ch=='-')f*=-1; ch=getchar(); } while(isdigit(ch)){ x=x*10+ch-'0'; ch=getchar(); } x*=f; } template<typename T> void write(T x){ if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+'0'); } //=========================================================== #define int ll ll h,n; int d[maxn]; int solve(){ int mx=0; for(int i=1;i<=n;i++){ d[i]+=d[i-1]; if(h+d[i]<=0)return i; mx=min(mx,d[i]); } if(d[n]>=0)return -1; int need=h+mx; //cerr<<"*"<<need<<endl; //cerr<<d[n]<<endl; int need_r=ceil(1.0*need/(-d[n])); //cerr<<need_r<<" "<<need_r*d[n]<<endl; h+=need_r*d[n]; for(int i=1;i<=n;i++){ if(h+d[i]<=0){ return need_r*n+i; } } exit(1); } signed main(){ //freopen("in.txt","r",stdin); read(h),read(n); for(int i=1;i<=n;i++)read(d[i]); write(solve()); return 0; }