【差分 最少操作】 Incdec sequence

传送门

题意

长度为\(n\)的数列,每次可以选择一个区间\([ l , r ]\) 使区间内的数都+1或-1,求至少需要多少次操作才能使数列中的所有数都一样,
并求出在保证最少次数的前提下,最终数列可能有多少种

数据范围

\(\begin{array}{l}0<n \leq 10^{5} \\ 0 \leq a_{i}<2147483648\end{array}\)

题解

\([l,r]\)全部加上一个数字是\(O(n)\)的利用差分可以做到\(O(1)\)
原序列的操作相当于在\(b\)中每次选两个位置一个 + 一个 - 或者相反,将\(b[2]\sim b[n]\)变成0,最后数列是由\(N\)\(b[1]\)构成,因为题目只要求了使数值一样
4种操作:

  1. $b_{i} , b_{j} , 2\leq i , j\leq n $尽可能选一正一负可以使二者在最少操作下都达到0

  2. \(b_{1} , b_{j} , 2\leq j\leq n,\)

  3. \(b_{j} , b_{n+1} , 2\leq j\leq n,\)

  4. \(b_{1} , b_{n+1} ,\)相当于不操作,一定不是最优

假设\(b\)中正数总和为\(p\),负数总和为\(q\),配对\(min(p,q)\)对,剩下的用2、3使的单个变为0
所以最少的操作数是\(min(p,q)+|p-q|=max(p,q)\)
根据\(|p-q|\)次第2、3类操作产生的不同的\(b_{1}\)值,因为只有第2种操作会影响第一个的值,所以最终的序列有\(|p-q|+1\)

Code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
ll a[N],b[N];
ll p,q;
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    b[1]=a[1];
    for(int i=2;i<=n;i++)
        b[i]=a[i]-a[i-1];

    for(int i = 2; i <= n; i++){
        if(b[i]<0) p-=b[i];//因为每次操作只能+1或者-1所以要取他们的和,即操作次数
        else if(b[i]>0) q+=b[i];
    }
    cout<<max(p,q)<<endl;
    cout<<abs(p-q)+1<<endl;
}
posted @ 2020-05-26 12:18  Hyx'  阅读(247)  评论(0编辑  收藏  举报