Codeforces 1141E Superhero Battle

求H首次为零的时段问题
本文介绍了一个关于寻找序列中生命值首次变为零的位置的问题,并提供了一种通过预处理最小前缀和来优化循环次数的方法。对于负和序列,通过计算循环次数和额外遍历来确定最终位置。

  • 题目大意: 给出长度为\(n\)的序列\(d_i\)和生命值\(H\),每次到达该位置后生命值更新为\(H+d_i\),求\(H\)首次为零的时段
  • 思路: 首先想到先跑\(\ | \frac{H}{\sum{d_i}}\ | -1\)次然后跑最后一轮,但是序列的最小前缀可能远远小于\(\sum{d_i}\),所以跑\(\ | \frac{H}{\sum{d_i}}\ | - \frac{minsum}{\sum{d_i}}\)次,然后暴力跑到\(H\)为0即可
#include<bits/stdc++.h>
 
#define ll long long 
#define FOR(i,n) for(int i =1; i <= n;++i ) 
#define FOR0(i,n) for(int i =0; i < n;++i )  
#define inf 0x3f3f3f3f
using namespace std;
 
const int maxn = 2*1e6+10;
 
ll H;
int n;
int a[maxn];
 
int main(){
    cin >>H >> n;
    ll tot = 0;
    ll mps = 0;
    ll HH = H;
    FOR(i,n){
        cin >> a[i];
        tot += a[i];
        HH+= a[i];
        mps = min(mps,tot);
        a[i+n] = a[i];
        if(HH<=0){
            cout <<i  << endl;
            exit(0);
        }
    }
    if(tot >=0){
        cout << -1 << endl;
    }else{
        ll len = H/(-1*tot);
        len = max(len-mps/tot,0LL);
        H+=len*tot;
        len *= n;
        while(H>0){
            FOR(i,n+n){
                H+= a[i];
               if(H<=0){
                   len += i;
                    break;
                }
            }
            if(H>0)
                len += n+n;
        }
        cout << len<<endl;
    }
 
    return 0;
}

被卡了两次,贪心也不能贪过头了

转载于:https://www.cnblogs.com/xxrlz/p/11223780.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值