牛客小白月赛104 C-小红打怪

小红打怪
答案有单调性,使用二分答案来做

但是当时没有想到用二分,而是卡在怎么处理这三种攻击了。

可以把进行x回合的攻击,分为先进行x回合的全体打击,再进行x回合的范围打击,最后验证剩余血量够不够x回合的单体打击

贪心的处理范围打击:对每一对相邻且都大于0的血量,这样最多只会浪费一点,举个例子对于0 0 1 2 3,进行两回合的打击会剩 0 0 0 1 3 然后0 0 0 0 2,如果只是对\(min(a_i,a_{i+1})\)处理,就会有很多点攻击浪费在尸体上

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
using pii=pair<int,int>;
int a[100005];
int b[100005];

bool check(int mid)
{
    for(int i=1;i<=n;i++)  b[i]=a[i]-mid; //进行a类的攻击
    int c=mid;
    for(int i=1;i<n;i++)
    {
        if(b[i]>0&&b[i+1]>0){//这样贪心保证了,这两次的攻击不会浪费有浪费在尸体上
        //别取等 ,取等就不是最优的去贪了
        
            int w=min({b[i],b[i+1],c});
            b[i]-=w,b[i+1]-=w,c-=w;//进行b类的攻击
            if(c==0) break;
        }
    }
    
    
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        if(b[i]>0) sum+=b[i]; //剩余的总的怪兽的体力
    }

    //此时mid为进行c类攻击的次数
    //变量名c是b类攻击还可以使用的次数
    return sum<=mid+c;
    
}



void solve()
{
    int n;
    cin>>n;
    
    for(int i=1;i<=n;i++) cin>>ve[i];
    int ans=0;
    int l=1,r=1e9;
    while(l<=r)
    {
        int mid=l+r>>1;
        if(check(mid)){
            ans=mid;
            r=mid-1;
        }else l=mid+1;
        
    }
    
    cout<<ans;
    
}

int main() {
  
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
  
    int t=1;
    //cin>>t;
    while(t--) solve();
    
    return 0;
}

posted on 2024-11-10 13:34  swj2529411658  阅读(4)  评论(0编辑  收藏  举报

导航