Sequence(AtCoder-2399)

本文探讨了一个整数序列的问题,目标是最小化操作次数,使序列的前缀和不为零且相邻前缀和的符号交替。通过枚举两种可能的符号序列,文章提供了一种算法解决方案,并附带源代码实现。

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

Problem Description

You are given an integer sequence of length N. The i-th term in the sequence is ai. 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 i (1≤i≤n), the sum of the terms from the 1-st through i-th term is not zero.
For every i (1≤i≤n−1), the sign of the sum of the terms from the 1-st through i-th term, is different from the sign of the sum of the terms from the 1-st through (i+1)-th term.

Constraints

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

Partial Score

Input is given from Standard Input in the following format:

n
a1 a2 … an

Input

The input is given from Standard Input in the following format:

N K
a1 a2 ... aN

Output

Print the minimum necessary count of operations.

Example

Sample Input 1

4
1 -3 1 0

Sample Output 1

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

Sample Input 2

5
3 -6 4 -5 7

Sample Output 2

0
The given sequence already satisfies the conditions.

Sample Input 3

6
-1 4 3 2 -5 4

Sample Output 3

8

题意:给出一个长度为 n 的序列 ai,每次可以选择任意一个数字将其 -1 或 +1,问当整个序列满足 1~i 个数字和不为 0 且 1~i-1 的和与 i 的正负相反时的最小操作步数

思路:

简单来说,就是当某个数不符合条件时,将其 -1 或 +1,考虑到要求满足的条件,1~n 个正负只可能是 正、负、正、负 ...,或 负、正、负、正 ...

那么对于以上两种情况按所给条件进行枚举,最后在两次枚举中选取第最小值即可

需要注意的是,由于第一个数可能为 0,因此一开始要进行判断

Source Program

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 100000+5;
const int dx[] = {-1,1,0,0,-1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;

LL a[N];
int main() {
    int n;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%lld",&a[i]);

    LL ans1=0,sum1=0;
    LL ans2=0,sum2=0;
    if(a[1]==0) {
        sum1=1;
        ans1=1;
        sum2=-1;
        ans2=1;
    } else if(a[1]>0) {
        sum1=a[1];
        sum2=-1;
        ans2=a[1]+1;
    } else {
        sum1=1;
        sum2=a[1];
        ans1=llabs(a[1])+1;
    }

    for(int i=2; i<=n; i++) {
        if(sum1>0) {
            if(a[i]+sum1<0)
                sum1+=a[i];
            else {
                ans1+=a[i]+sum1+1;
                sum1=-1;
            }
        } else {
            if(a[i]+sum1>0)
                sum1+=a[i];
            else {
                ans1+=llabs(sum1+a[i])+1;
                sum1=1;
            }
        }
    }
    if(sum1==0)
        ans1++;

    for(int i=2; i<=n; i++) {
        if(sum2>0) {
            if(a[i]+sum2<0)
                sum2+=a[i];
            else {
                ans2+=a[i]+sum2+1;
                sum2=-1;
            }
        } else {
            if(a[i]+sum2>0)
                sum2+=a[i];
            else {
                ans2+=llabs(sum2+a[i])+1;
                sum2=1;
            }
        }
    }
    if(sum2==0)
        ans2++;

    LL res=min(ans1,ans2);
    printf("%lld\n",res);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值