div3-1674E. Breaking the Wall

Problem E
分类讨论

题意

给你一个 n n n 个元素的数组 A ( 1 ≤ a i ≤ 1 e 6 ) A(1\leq a_i\leq 1e6) A(1ai1e6),每次操作可以 ∀ i ∈ [ 1 , n ] \forall i\in [1,n] i[1,n],将 a i a_i ai 减少2, a i − 1 , a i + 1 a_{i-1},a_{i+1} ai1,ai+1 各减少1,问最少多少次操作可以使数组中至少两项小于等于0。

思路

观察容易发现,我们进行操作位置至多只有两个,相对应的,设最终小于等于0的两项下标分别为 i , j i,j i,j
i , j i,j i,j 一定满足以下3种条件之一:

  1. i , j i,j i,j 相邻,如 [ 1000 , 3 , 3 , 1000 ] [1000,3,3,1000] [1000,3,3,1000]
  2. i , j i,j i,j 间隔为1,如 [ 5 , 100 , 3 ] [5,100,3] [5,100,3] [ 4 , 100 , 4 ] [4,100,4] [4,100,4]
  3. i , j i,j i,j 间隔大于1,如 [ 3 , 100 , 100 , 3 ] [3,100,100,3] [3,100,100,3]

先考虑第三种情况, i , j i,j i,j 独立,答案就是 ( a i + 1 ) / 2 + ( a j + 1 ) / 2 (a_i+1)/2+(a_j+1)/2 (ai+1)/2+(aj+1)/2
对第二种情况,注意到如果 a i , a i + 2 a_i,a_{i+2} ai,ai+2 不全为奇数,那么可以采用第三种方法,否则可以先对 i + 1 i+1 i+1 进行一次操作将 a i , a i + 2 a_i,a_{i+2} ai,ai+2 变为偶数再进行操作3,答案会少1。
最后考虑第一种情况,假设 a i ≥ a j a_i\geq a_j aiaj,若 a i ≥ 2 a j a_i \geq 2a_j ai2aj ,则答案显然为 ( a i + 1 ) / 2 (a_i+1)/2 (ai+1)/2,否则答案为 ( a i + a j + 2 ) / 3 (a_i+a_j+2)/3 (ai+aj+2)/3

对第一种情况的简单证明:

  1. a i ≥ 2 a j a_i \geq 2a_j ai2aj 显然仅对 i i i 操作,次数为 ( a i + 1 ) / 2 (a_i+1)/2 (ai+1)/2
  2. 因为一定可以通过若干次操作使得 a i ′ = a j ′ a_i' = a_j' ai=aj。接下来对于两个相等的数,在操作的过程中, ∣ a i − a j ∣ ≤ 1 |a_i-a_j|\leq 1 aiaj1 恒成立,所以一定会转移到(1,0)(0,1)(0,0)(1,1)四种中的一种,其实对应的就是(a+b)%3的值,因为每次减3所以如果(a+b)%3=2 最后就会转移到(1,1)…不管是哪种,转移到这四种的次数都是 ( a + b ) / 3 (a+b)/3 (a+b)/3 向下取整,而对于 (a+b)%3 != 0 的情况还需要再+1,所以最终答案就是 ( a + b + 2 ) / 3 (a+b+2)/3 (a+b+2)/3

代码

int a[maxn];
void solve() {
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    int ans = INF;
    a[n+1] = a[0] = INF;
    for(int i = 1; i <= n; i++) {
    	int q = max(a[i], a[i+1]);
    	int p = min(a[i], a[i+1]);
    	int tmp = 0;
    	if(q >= 2*p) {
    		tmp = (q+1) >> 1;
    	}
    	else {
    		tmp = (p + q + 2) / 3;
    	}
    	ans = min(ans, tmp);
    	if((a[i-1]&1) && (a[i+1] & 1)) {
    		ans = min(ans, a[i-1]/2+a[i+1]/2+1);
    	}
    }
    sort(a + 1, a + n + 1);
    ans = min(ans,(a[1]+1)/2 + (a[2]+1)/2);
    cout << ans << endl;
}
  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值