差分陣列練習2

2021-08-02 20:12:53 字數 1525 閱讀 5942

加減序列

給定乙個長度為n的數列,每次可以選擇乙個區間[l,r],使這個區間內的數都加一或者都減一。

問至少需要多少次操作才能使數列中的所有數都一樣,並求出在保證最少次數的前提下,最終得到的數列有多少種。

第一行乙個正整數n

接下來n行,每行乙個整數,第i+1行的整數表示ai。

第一行輸出最少操作次數

第二行輸出最終能得到多少種結果

411

22

1

2

n=100000,0<=ai<2147483648

這題跟練習1一樣,都是要用差分陣列來實現的。首先讀題,同樣是要求區間加一或減一,不同的是它讓你將這個數列中的數相同。這題一共有兩小問。先來看第一小問,第一小問要求我們輸出最少的操作次數。以1 1 2 0為例,我們來把差分陣列列出來,可以得到1 0 1 -2.因為題目只是要求將所有數變為相同的,所以第乙個數可以不用管它。然後我們會發現除去第乙個數的其他差分陣列中的正數和負數可以相互抵消,但每抵消1個單位就等於一次操作,因此最少的操作次數為max(s1,s2)(s1為差分陣列中所有正數之和,s2為差分陣列中所有負數絕對值之和)。再來看第二小問很顯然為了達到最小步數我們必須先把正數和負數能抵消的全部抵消,而這些步驟最多只有一種情況,因此可以不考慮。但是抵消到只剩下正數或只剩下負數時,就會出現不同的情況。比如0 0 -1 0這個差分陣列,其中的-1可以與第乙個數抵消(相當於把前兩個數加一),或者與最後乙個數的後面抵消(相當於把第三和第四個數都加一),再看0 0 2 0,其中的2可以全部與第乙個數抵消,也可全部與最後乙個數的後面抵消,也可以其中乙個與第乙個數抵消,另乙個數與最後乙個數後面抵消。因此我們可以得到這樣乙個規律,第二個答案就是abs(s1-s2)+1。

ac**:

#include

#include

#define ll long

long

using

namespace std;

int a[

100005

],c[

100005

],n;

lls1,s2;

llab(ll

x)llmx(

llx,

lly)

intmain

()for

(int i=

1;i<=n;i++)

for(

int i=

2;i<=n;i++)

cout<<

mx(s1,s2)<

ab(s1-s2)+1;

return0;

}

ac截圖:

這題跟練習1一樣,都是要用差分陣列來實現的。首先讀題,同樣是要求區間加一或減一,不同的是它讓你將這個數列中的數相同。這題一共有兩小問。先來看第一小問,第一小問要求我們輸出最少的操作次數。

差分陣列概述

在網上講差分陣列的博文很少,也很難找到。一度以為差分陣列是傳播於小眾的神犇技巧所以一直放著沒有去研習。今天做了 bzoj1635後發現各路神犇都用差分陣列,本蒟卻傻傻寫了線段樹。對於序列a 取a i a i 1 為其差分陣列b i 的值,可以發現,a i bj 1 j i 如 對於序列 a b c ...

港口 差分陣列)

傳送門 思路 因為是區間加減,所以考慮差分陣列,題意變為 要求差分陣列d 2 d 3 d n d 2 d 3 dots d n d 2 d 3 d n 全為0.每次區間加或減會使差分陣列乙個加1,乙個減1,因為要用最小次數,所以每次操作最好產生有效貢獻,可知當為正數或負數的差分陣列變為0後,剩下我們...

差分陣列詳解

學習部落格 題目 來先看一道裸題,有n個數。m個操作,每一次操作,將x y區間的所有數增加z 最後有q個詢問,每一次詢問求出x y的區間和。思路 很明顯,直接用字首和無法快速滿足這個操作,所以我們就用到了差分陣列。設a陣列表示原始的陣列 設d i a i a i 1 1設f i f i 1 d i ...