小红打怪
答案有单调性,使用二分答案来做
但是当时没有想到用二分,而是卡在怎么处理这三种攻击了。
可以把进行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;
}
标签:打怪,int,sum,mid,回合,牛客,攻击,104
From: https://www.cnblogs.com/swjswjswj/p/18537885