欢迎光临
我们一直在努力

【题解-Acwing】100. 增减序列

题目:100. 增减序列

题目描述

给定一个长度为 n 的数列 a1,a2,…,an,每次可以选择一个区间 [l,r],使下标在这个区间内的数都加一或者都减一。

求至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列可能有多少种。

输入格式

第一行输入正整数 n。

接下来 n 行,每行输入一个整数,第 i+1 行的整数代表 ai。

输出格式

第一行输出最少操作次数。

第二行输出最终能得到多少种结果。

数据范围

0 < n ≤ 105 , 0 ≤ ai < 2147483648

时空限制

1s / 64MB

输入样例

4
1
1
2
2

输出样例

1
2

思路(《算法进阶指南》)

本题目可以通过求a的差分序列b来求解,这样可以把对a序列的区间操作,转化为对b序列中两个值的操作。 b1 = a1,bi = ai – ai-1(2 ≤ i ≤ n)。令bn+1 = 0 题目转化为: 把b2,b3,…,bn变为0,b1为常数。

从b1,b2,…,bn+1中任选两个数的方法可以分为四类:

  • 2 ≤ L ≤ R ≤ n-1,令某个数+1,另一个数-1
  • L = 1, R ≤ n-1,b1 +1/-1,b2 ~ bn中某个数 -1/+1
  • 2 ≤ L, R = n,bn+1 +1/-1,b2 ~ bn中某个数-1/+1
  • L=1,R=n,会实现对整个区间的数+1/-1,没有意义
  • 设b2,b3,…,bn中正数总和为p,负数总和的绝对值为q。 为了让操作次数最少,应该尽量执行第1类操作,可执行min(p, q)次。剩余|p – q|个未配对,每个执行第2或第3类操作,共需|p – q|次。 综上,最少操作次数为min(p, q) + |p – q| = max(p, q)次。根据 |p – q|次第2、3类操作的选择,能产生 |p – q| + 1种不同的b1值,即最终得到的序列a可能有|p – q| + 1种。

    代码

    #include<bits/stdc++.h>

    using namespace std;

    typedef long long LL;
    const int N = 1e5 + 10;

    int n, b[N];
    LL p, q; //p为b数组正数之和,q为b数组负数之和

    void insert(int l, int r, int c){
    b[l] += c;
    b[r + 1] -=c;
    }

    int main(){
    cin >> n;
    for(int i = 1; i <= n; i ++){
    int c;
    cin >> c;
    insert(i, i, c);

    if(i > 1){
    if(b[i] > 0) p += b[i];
    else q -= b[i];
    }

    }

    cout << min(p, q) + abs(p – q) << endl;
    cout << abs(p – q) + 1;
    return 0;
    }

    结果

    在这里插入图片描述

    赞(0)
    未经允许不得转载:171主机测评 » 【题解-Acwing】100. 增减序列
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址