C:小红打怪

题目要求击杀所有怪兽的最少回合,如果 x 个回合可以击杀完,那么 (x+1) 回合肯定也可以击杀完,答案满足单调性,所以考虑二分。

至于该怎么判断是否 x 回合可以击杀完所有怪兽,就是遍历怪兽,处理血量大于 limit 的怪兽,因为小于等于 limit 的可以通过小红的集体伤害减为 0,所以我们只考虑大于 limit 的怪兽;如果第 i 只怪兽以及第 i+1 只怪兽血量都大于limit,那么我们使用队友 2 的技能,用一个技能攻击两只怪兽;否则就用队友 1 的技能,对单只怪兽造成伤害。

(不能对原数组排序哦,排序会影响怪兽的相邻关系)

具体细节请看代码,写了非常详细的注释


#include<bits/stdc++.h>
using namespace std;
#define int long long

int t,n,m;
bool check(vector<int>a, int limit)//check函数里的数组a不能对外面的数组造成变化,否则会影响以后的check
{
	int cnt1=limit;//队友1的技能还能使用的次数
	int cnt2=limit;//队友2的技能还能使用的次数
	for(int i=0;i<n;i++)
	{
		if(a[i]>limit)
		{
			if(a[i+1]>limit && cnt2>0)//如果下一只怪兽血量也是 > limit,以及队友 2 的技能次数>0,还能用
			{
				int temp=min(a[i],a[i+1])-limit;
				if(cnt2>=temp)//如果队友2技能次数可以使得怪兽i的血量减到limit
				{
					cnt2-=temp;
					a[i]-=temp,a[i+1]-=temp;
				}
				else//如果不够,那就全部用掉
				{
					a[i]-=cnt2,a[i+1]-=cnt2;
					cnt2=0;//队友2技能不能再用了
				}
			}
			if(a[i]>limit)//单只怪兽血量 > limit 或者 上面的if还没有完全处理完a[i],就是还没有将a[i]降到limit
			{
				int temp=a[i]-limit;//需要使用这么多次队友1的技能
				if(cnt1>=temp)
				{
					cnt1-=temp;
					a[i]-=temp;
				}
				else
				{
					a[i]-=cnt1;
					cnt1=0;
					if(cnt2>=a[i]-limit)//队友1技能使用次数不够了,用队友2的技能
					{
						int temp2=a[i]-limit;
						a[i]-=temp2;
						cnt2-=temp2;
						//a[i] -= a[i]-limit;
						//cnt2 -= a[i]-limit;//写成这样不对哦,因为a[i]会被改变
					}
					else
						return false;//如果队友2的技能也不能用了,那就说明用 limit 回合是不能击杀所有怪兽的,返回false
				}
			}
		}
	}
	return true;
}
void solve(){
	cin>>n;
	vector<int> v(n+5);
	int mx=0;
	for(int i=0;i<n;i++){
		cin>>v[i];
		mx=max(mx,v[i]);
	};
	int l=0,r=mx;
	int ans=0;
	while(l<=r)
	{
		int mid=(r-l)/2+l;
		if(check(v, mid))
		{
			ans=mid;
			r=mid-1;
		}
		else
			l=mid+1;
	}
	cout<<ans<<endl;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	t=1;
	//cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

如果题解对你有所帮助,还请给我点个赞,谢谢!