E. Breaking the Wall

题目:E. Breaking the Wall

题意:给定长度为 n n n 的数组 a a a,求将数组中任意的两个值减小到 0 0 0 的最小操作次数。每次操作可以选择一个 1 ≤ i ≤ n 1 \leq i \leq n 1in ,使得, a [ i ] = a [ i ] − 2 , a [ i − 1 ] = a [ i − 1 ] − 1 , a [ i + 1 ] = a [ i + 1 ] − 1 a[i] = a[i] - 2,a[i-1] = a[i-1] - 1,a[i+1] = a[i+1] - 1 a[i]=a[i]2,a[i1]=a[i1]1,a[i+1]=a[i+1]1 1 ≤ a i ≤ 1 0 6 1 \leq a_i \leq 10^6 1ai106

思路:由题意可得,需要选择两个值,将其值变为 0 0 0 ,每一次操作至少会改变两个值,所以存在以下的几种情况:

  • 选择的两个值间隔大于 2 2 2 ( ∣ i − j ∣ > 2 ) (|i - j| > 2) (ij>2)
  • 选择的两个值间隔等于 2 2 2 ,两者之间不能相互影响, ( ∣ i − j ∣ = 2 ) (|i - j| = 2) (ij=2)
  • 选择的两个值间隔小于 2 2 2 ,两者之间能相互影响, ( ∣ i − j ∣ < 2 ) (|i - j| < 2) (ij<2)

对于第一种情况,只需找出数组 a a a 中的最小的两个值 a i a_i ai a j a_j aj ,计算出将这两个值变为 0 0 0 的最小操作 ⌈ a i / 2 ⌉ + ⌈ a j / 2 ⌉ \lceil a_i/2 \rceil + \lceil a_j/2 \rceil ai/2+aj/2

对于第二种情况,需要遍历整个数组,比较最小操作数 m i n ( ⌈ a i / 2 ⌉ + ⌈ a i + 2 / 2 ⌉ , ⌈ ( a i − 1 ) / 2 ⌉ + ⌈ ( a i + 2 − 1 ) / 2 ⌉ + 1 ) min(\lceil a_i/2\rceil + \lceil a_{i+2}/2 \rceil,\lceil (a_i-1)/2\rceil + \lceil (a_{i+2} - 1)/2 \rceil + 1) min(ai/2+ai+2/2,(ai1)/2+(ai+21)/2+1) ( 1 ≤ i ≤ n − 2 ) (1\leq i \leq n-2) (1in2) ⌈ ( a i − 1 ) / 2 ⌉ + ⌈ ( a i + 2 − 1 ) / 2 ⌉ + 1 ) \lceil (a_i-1)/2\rceil + \lceil (a_{i+2} - 1)/2 \rceil + 1) (ai1)/2+(ai+21)/2+1) 的意思是,先为 a i + 1 a_{i+1} ai+1 进行一次操作,目的是为了让 a i a_i ai a i + 2 a_{i+2} ai+2 同时减 1 1 1

对于第三种情况,也需要遍历整个数组,比较最小操作数,假设对 a i a_i ai 进行 x x x 次操作,对 a i + 1 a_{i+1} ai+1 进行 y y y 次操作,则有如下两个不等式

  • 2 ∗ x + y ≥ a i 2 * x + y \geq a_i 2x+yai
  • x + 2 ∗ y ≥ a i + 1 x + 2 *y \geq a_{i+1} x+2yai+1

合并不等式 3 ∗ x + 3 ∗ y ≥ a i + a i + 1    ⟹    x + y ≥ ( a i + a i + 1 ) / 3    ⟹    x + y = ⌈ ( a i + a i + 1 ) / 3 ⌉ 3 * x + 3 * y \geq a_i + a_{i+1} \implies x + y \geq (a_i + a_{i+1}) / 3 \implies x + y = \lceil (a_i + a_{i+1}) / 3 \rceil 3x+3yai+ai+1x+y(ai+ai+1)/3x+y=(ai+ai+1)/3 ,此处一定要注意 x + y x + y x+y 不一定是正确的操作数 ( a i = 0 , a i + 1 = 3 ) (a_i = 0,a_{i+1} = 3) (ai=0,ai+1=3),所以最终的表达式为 m a x ( ⌈ ( a i + a i + 1 ) / 3 ⌉ , ⌈ a i / 2 ⌉ , ⌈ a i + 1 / 2 ⌉ ) max(\lceil (a_i + a_{i+1}) / 3 \rceil,\lceil a_i / 2 \rceil,\lceil a_{i+1}/2 \rceil) max((ai+ai+1)/3,ai/2,ai+1/2) ,最后取每个结果的 m i n min min

#include<stdio.h>
#include<math.h>
#include<algorithm>

using namespace std;
const int N = 2e5 + 10;
int a[N]; 

int main(){
	int n;
	int d1 = 0x3f3f3f3f,d2 = 0x3f3f3f3f;
	
	scanf("%d",&n);
	
	for(int i=1;i<=n;i++) {
		scanf("%d",&a[i]);
		if(d1 > a[i]) {
			d2 = d1;
			d1 = a[i]; 
		}
		else if(d2 > a[i]) {
			d2 = a[i];
		}
	}
	
	int res = d1 / 2 + d2 / 2;
	
	if(d1 % 2) res ++;
	if(d2 % 2) res ++;
	
	
	for(int i=2;i<n;i++) {
		double A = a[i - 1];
		double B = a[i];
		double C = a[i + 1];
		
		res = min(res,(int)min(ceil((A-1)/2)+ceil((C-1)/2) + 1,ceil(A/2)+ceil(C/2)));
		
		res = min(res,(int)max({ceil(A / 2),ceil(B / 2),ceil((A+B)/3)}));
		res = min(res,(int)max({ceil(C / 2),ceil(B / 2),ceil((C+B)/3)}));
	}
	
	res = min(res,(int)max({ceil((double)a[1] / 2),ceil((double)a[2] / 2),ceil((double)(a[1]+a[2])/3)}));
	res = min(res,(int)max({ceil((double)a[n] / 2),ceil((double)a[n-1] / 2),ceil((double)(a[n]+a[n-1])/3)}));
	
	
	printf("%d\n",res);
	
	return 0;
}
/*
2
0 3
*/
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值