Break the wall 1674E

Problem - 1674E - Codeforces

题意:一组数据,1 - n ,可以选一个目标位置,x 使其 - 2 ,同时 x - 1 , x + 1 减 1,求最小操作次数,使得原数组出现两个0.

分类:

1. 这两个位置 , 不相邻 , 那么就是独立,每个都通过 - 2 变成 0 , 那么一定是最小的两个数,可以满足这个条件 , 排序后的 (v[1]  + 1) / 2 + (v[2] + 1) / 2)为这种情况的最小值.

2.相隔为1 , 如果都是奇数,那么先操作中间两边都-1,变成偶数,每次都是 - 2 ,总操作数 - 1,

如果是其他情况, 那么他的最小值是 分别把每一个变成 0 。

3.相邻,ai (a) , ai-1(b) ,

假设 a > b; 

一个-2 ,另一个 - 1,如果 a >= 2*b ,一直对a操作,a变成0,b也一定是0,那么就得到 --- >

(a + 1) / 2 为这个情况的最小值

a < 2b , 那么 a - 2 * x = b - x; 得到 x = a - b; 因为 a < 2b 所以 a - b < b; x取值是一个小于b的数,说明在b变为0之前,可以有a == b ,当 a == b时 每次操作都能保证 |a - b| <= 1,那么最后结果一定是 a = 0,b = 1 ; a = 0 ,b = 0; a = 1,b = 1;a = 1,b = 0;其中之一,对于不是 a = 0,b = 0的情况,需要多操作一次,也就是 % 3有余数时,需要 + 1,那么就是上除整的操作,那么最小值为 (a + b + 2) / 3;

综上

ans = min ((a + b + 2) / 3 ,  (a + 1) / 2 , (v[1]  + 1) / 2 + (v[2] + 1) / 2); 

代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int a[3000010];
int b[3000010];
void solve()
{   int n;
    cin >> n;
    for(int i = 1; i <= n ; i ++ )
    {
        cin >> a[i];
        b[i] = a[i];
    }
    sort(b+1,b+1+n);
    ll ans = (b[1] + 1) / 2 + (b[2] + 1) / 2;

    for(int i = 2; i <= n ; i ++ )
    {
        ll t;
        int k1 = a[i] ;
        int k2 = a[i-1] ;
        if(max(k1,k2) >= 2*min(k1,k2))
        {
            ans = min(int(ans) ,(max(k1,k2) + 1)/2);
        }
        else
        {
            ans = min((int)ans , (k1 + k2 + 2) / 3);
        }
        if(i != n)
        {
         t = min(a[i-1],a[i+1]);
         t += (max(a[i-1],a[i+1]) - min(a[i-1],a[i+1]) + 1) / 2;
         ans = min(ans , t);
        }
    }
    cout << ans << endl;
    return ;
}
int main()
{
    solve();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值