C - Sequence(思维+贪心)

本文探讨了一道算法题目,要求通过最少次数的操作使序列中每个前缀和的符号交替出现。介绍了问题背景,提出了解决方案,并给出了具体实现代码。通过实例展示了如何将序列转换以满足条件,最终求得最少操作次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Statement

You are given an integer sequence of length NN. The ii-th term in the sequence is aiai. In one operation, you can select a term and either increment or decrement it by one.

At least how many operations are necessary to satisfy the following conditions?

  • For every ii (1≤i≤n)(1≤i≤n), the sum of the terms from the 11-st through ii-th term is not zero.
  • For every ii (1≤i≤n−1)(1≤i≤n−1), the sign of the sum of the terms from the 11-st through ii-th term, is different from the sign of the sum of the terms from the 11-st through (i+1)(i+1)-th term.

Constraints

  • 2≤n≤1052≤n≤105
  • |ai|≤109|ai|≤109
  • Each aiai is an integer.

Input

Input is given from Standard Input in the following format:

nn
a1a1 a2a2 ...... anan

Output

Print the minimum necessary count of operations.


Sample Input 1 Copy

Copy

4
1 -3 1 0

Sample Output 1 Copy

Copy

4

For example, the given sequence can be transformed into 1,−2,2,−21,−2,2,−2 by four operations. The sums of the first one, two, three and four terms are 1,−1,11,−1,1and −1−1, respectively, which satisfy the conditions.


Sample Input 2 Copy

Copy

5
3 -6 4 -5 7

Sample Output 2 Copy

Copy

0

The given sequence already satisfies the conditions.


Sample Input 3 Copy

Copy

6
-1 4 3 2 -5 4

Sample Output 3 Copy

Copy

8

题意:
每一次操作你可以选择一个数让这个数加一或减一。要求前i个数的和与前i+1个数的和一正一负,或一负一正(不能为0)。

问你最少要操作多少次。

思路:
如果当前这个数不满足,那么到当前这个数的和要么改成-1,要么是+1,这样才能保证操作最少。(这里第一个数要先讨论一下)。

代码:
 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a[100009];
ll sum1=0,sum2=0;//sum1是第一个数为整数。(不是正数就改为-1).sum2则相反。
ll ans1=0,ans2=0;//对应的操作数。
int main()
{
    int n;
    cin>>n;
    for(int i=1; i<=n; i++)
    {
        cin>>a[i];
    }
    if(a[1]>0)
    {
        sum1=a[1];
        ans2=a[1]+1;
        sum2=-1;
    }
    else if(a[1]==0)
    {
        sum1=1;
        ans1=1;
        ans2=1;
        sum2=-1;
    }
    else
    {
        sum1=1;
        ans1=abs(a[1])+1;
        sum2=a[1];
    }
    for(int i=2; i<=n; i++)
    {
        if(sum1>0)
        {
            if(sum1+a[i]>=0)
            {
                ans1+=sum1+a[i]+1;
                sum1=-1;
            }
            else
            {
                sum1+=a[i];
            }
        }
        else if(sum1<0)
        {
           if(sum1+a[i]<=0)
           {
               ans1+=abs(sum1+a[i])+1;
               sum1=1;
           }
           else
           {
               sum1+=a[i];
           }
        }
    }
    if(sum1==0)
    {
        ans1++;
    }


    for(int i=2; i<=n; i++)
    {
        if(sum2>0)
        {
            if(sum2+a[i]>=0)
            {
                ans2+=sum2+a[i]+1;
                sum2=-1;
            }
            else
            {
                sum2+=a[i];
            }
        }
        else if(sum2<0)
        {
           if(sum2+a[i]<=0)
           {
               ans2+=abs(sum2+a[i])+1;
               sum2=1;
           }
           else
           {
               sum2+=a[i];
           }
        }
    }
    if(sum2==0)
    {
        ans2++;
    }
    cout<<min(ans1,ans2)<<endl;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值