IncDec Sequence(增减序列)Acwing102 —— 前缀和、差分

IncDec Sequence(增减序列)Acwing102

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

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

输入格式
第一行输入正整数n。

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

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

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

数据范围
0<n≤10^5,
0≤ai<2147483648
输入样例:
4
1
1
2
2
输出样例:
1
2

/*
题意:对区间(l , r)中的元素加减一操作使得整个数列为常数列最少需要操作多少次,最终的常数列有多少种

这种需要对区间每个元素操作的方法很快就能想到 前缀和与差分, 这题使用差分序列完成。
差分决策:
只需要将[2 ~ N]中的差分序列全部变为0即可。
选择区间的可能:
1、 2 <= i , j <= N 尽可能的选择一正一负的i ,j保证接近目标
2、 i = 1, 2 <= j <= N 
3、 j = 1, 2 <= i <= N
——2 、3 将i,j配对化为其中一个
4、 i = 1 , j = N 毫无意义

其中假设序列中正整数总和为p、负整数为q。则先采用第一种方案最少需要执行min(p, q)种操作。
剩余| p - q |个未匹配的采用第2、 3种方案化为其中的一个数。所以总操作次数未min(p, q) + |p - q|
一共可以产生|p - q| + 1种数列
*/

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

typedef long long LL;

const int N = 1e5 + 10;
int a[N];

int main(){
    
    
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++)cin >> a[i];
    for(int i = n; i > 1; i-- ) a[i] -= a[i - 1];//计算差分序列
    
    LL pos = 0, neg = 0;
    for(int i = 2; i <= n; i++){
    
    
        if(a[i] > 0)pos+=a[i];//计算正整数的总和
        else neg -= a[i];//计算负整数的总和
    }
    cout << min(pos, neg) + abs(pos - neg) << endl;
    cout << abs(pos - neg) + 1 << endl;
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45830383/article/details/108686010