增減序列

增減序列

最終的目的是讓整個序列相等ios

操做只有一種使\([l,r]\)區間全都\(+1\)spa

既然整個序列相等,那麼整個序列的差分序列應爲0code

操做的話就能夠轉化爲\(a[l]+=1,a[r+1]-=1\)ip

求的是最少操做次數ci

經過原數列,咱們先求一個原始的差分序列,而後每次操做使,正數-1,負數+1,這樣就使差分序列往目標:靠近 0序列
(固然差分序列第1項不用爲0,並且首項能夠爲任何數,思考爲何?)get

設正數的和p,負數絕對值和q,那麼就很容易的到一個最少操做次數 \(max(p,q)\)
(簡單描述下怎麼來的,操做\(min(p,q)\)次後,p,q中小的變爲0,還剩\(abs(p-q)\)次 ,因此最少操做次數 \(min(p,q)+abs(p-q)=max(p,q)\))io

至於最少操做後的結果class

操做\(min(p,q)\)次後,那麼必定剩下幾項不爲0
此時能夠考慮兩中狀況stream

  1. 與差分序列首項想相加減
    這種狀況由於改變首項,因此最終序列會改變,故會獲得\(abs(p-q)\)種序列思考

  2. 與第\(n+1\)項相加減
    這種狀況並不改變首項,只有一種序列(第n+1項不管怎麼變,都不影響最終序列,也能夠思考爲何)

總的來講會獲得\(abs(p-q)+1\)種方案

  • code
#include<iostream>

using namespace std;
const int maxn=1e5+10;
int a[maxn];int n;
int cf[maxn];
long long p=0,q=0;
long abs(long x){
    return x<0?-x:x;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;++i){
        cin>>a[i];
        cf[i]=a[i]-a[i-1];
    }
    for(int i=2;i<=n;++i){
        if(cf[i]>0) p+=cf[i];
        if(cf[i]<0) q-=cf[i];
    }
    cout<<max(p,q)<<endl<<abs(p-q)+1<<endl;return 0;
}
相關文章
相關標籤/搜索