Codeforces Round #786 (Div. 3)E、Breaking the Wal

题意:
攻击一行数,任意选择一个,攻击某位置可以使得该位置-2,相邻位置-1.求使得两个为0的最小值。

题解:
把所有可能最小的情况求出,再取最小。
大概推推可以发现,最小值会出现这三种情况中:
1.相邻:
假定其为a,b。
如果a大于等于b的两倍,那么mmin此时与(a+1)/2比较。因为只对a操作b一定能归0。b大于等于二倍的a类似。(wa的原因就是忽略了这种情况55)
如果都不满足呢。其实是和除以3向上取整,因为对一次操作来说,其实是对和作用了3。写个例子就能很清楚的推出了。
2.相隔1:
假设顺序为a,b,c。
求出a,c最小的,可以对中间操作该次数使得最小归0,另一个减少它。然后对剩余值除以2向上取整即可。
3.其它。
那就是最小和次小分别进行除以2向上取整操作即可。

代码如下:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define sc scanf
#define pr printf
const int maxn=2e5+7;
int a[maxn];
#define ll long long 
int main() {
	int n;cin>>n;
	int mmin=INT_MAX;
	int mini=-1;
	int mmin1=INT_MAX;
	int mmin2=INT_MAX;
	for(int i=0;i<n;i++){
		sc("%d",&a[i]);
		if(i>0){//相邻最小 
			if(a[i]>=2*a[i-1])mmin=min(mmin,(a[i]+1)/2);
			else if(a[i-1]>=2*a[i])mmin=min(mmin,(a[i-1]+1)/2);
			else 
		    mmin=min(mmin,(a[i]+a[i-1]+2)/3);
    	}
		if(i>1&&a[i-1]>min(a[i-2],a[i])){//间隔为1最小 
			int b=max(a[i-2],a[i]),s=min(a[i-2],a[i]);
			mmin=min(mmin,s+((b-s)+1)/2);
		}
		if(i==1){//找出最小的两个数。mmin2最小,mmin2次小。 
			mmin1=max(a[0],a[1]);
			mmin2=min(a[0],a[1]);
		}
		else if(i>1){
			if(mmin2>a[i]&&mmin1>a[i]){
				mmin1=mmin2;
				mmin2=a[i];
			}
			else if(mmin1>a[i])mmin1=a[i];
		}
		
	}
	mmin=min(mmin,(mmin1+1)/2+(mmin2+1)/2);
	cout<<mmin<<endl;
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值