Acwing演算法基礎 2 6 差分

2021-10-22 14:22:57 字數 1557 閱讀 7589

原文:原文連線

類似於數學中的求導和積分,差分可以看成字首和的逆運算。

差分陣列:

首先給定乙個原陣列a:a[1], a[2], a[3], a[n];

然後我們構造乙個陣列b : b[1] ,b[2] , b[3], b[i];

使得 a[i] = b[1] + b[2 ]+ b[3] +, + b[i]

也就是說,a陣列是b陣列的字首和陣列,反過來我們把b陣列叫做a陣列的差分陣列。換句話說,每乙個a[i]都是b陣列中從頭開始的一段區間和。

考慮如何構造差分b陣列?

最為直接的方法

如下:a[0 ]= 0;

b[1] = a[1] - a[0];

b[2] = a[2] - a[1];

b[3] =a [3] - a[2];

b[n] = a[n] - a[n-1];

圖示:我們只要有b陣列,通過字首和運算,就可以在o(n) 的時間內得到a陣列 。

知道了差分陣列有什麼用呢? 別著急,慢慢往下看。

話說有這麼乙個問題:

給定區間[l ,r ],讓我們把a陣列中的[ l, r]區間中的每乙個數都加上c,即 a[l] + c , a[l+1] + c , a[l+2] + c , a[r] + c;

暴力做法是for迴圈l到r區間,時間複雜度o(n),如果我們需要對原陣列執行m次這樣的操作,時間複雜度就會變成o(n*m)。有沒有更高效的做法嗎? 考慮差分做法。

始終要記得,a陣列是b陣列的字首和陣列,比如對b陣列的b[i]的修改,會影響到a陣列中從a[i]及往後的每乙個數。

首先讓差分b陣列中的 b[l] + c ,a陣列變成 a[l] + c ,a[l+1] + c, a[n] + c;

然後我們打個補丁,b[r+1] - c, a陣列變成 a[r+1] - c,a[r+2] - c,a[n] - c;

為啥還要打個補丁?

我們畫個圖理解一下這個公式的由來:

b[l] + c,效果使得a陣列中 a[l]及以後的數都加上了c(紅色部分),但我們只要求l到r區間加上c, 因此還需要執行 b[r+1] - c,讓a陣列中a[r+1]及往後的區間再減去c(綠色部分),這樣對於a[r] 以後區間的數相當於沒有發生改變。

因此我們得出一維差分結論:給a陣列中的[ l, r]區間中的每乙個數都加上c,只需對差分陣列b做 b[l] + = c, b[r+1] - = c。時間複雜度為o(1), 大大提高了效率。

總結:字首和與差分的個人心得總結

ac**

//差分 時間複雜度 o(m)

#include

using namespace std;

const

int n =

1e5+10;

int a[n]

, b[n]

;int

main()

int l, r, c;

while

(m--

)for

(int i =

1; i <= n; i++

)return0;

}

acwing寒假演算法基礎 差分

傳送門 輸入乙個長度為n的整數序列。接下來輸入m個操作,每個操作包含三個整數l,r,c,表示將序列中 l,r 之間的每個數加上c。請你輸出進行完所有操作後的序列。第一行包含兩個整數n和m。第二行包含n個整數,表示整數序列。接下來m行,每行包含三個整數l,r,c,表示乙個操作。共一行,包含n個整數,表...

AcWing 差分矩陣 二維差分

時 空限制 1s 64mb 輸入乙個n行m列的整數矩陣,再輸入q個操作,每個操作包含五個整數x1,y1,x2,y2,c,其中 x1,y1 和 x2,y2 表示乙個子矩陣的左上角座標和右下角座標。每個操作都要將選中的子矩陣中的每個元素的值加上c。請你將進行完所有操作後的矩陣輸出。第一行包含整數n,m,...

ACWING演算法經典 797 一維差分演算法

原題鏈結 寫法一 先構造查分數列b n include using namespace std const int n 100010 int n,m,l,r,c int a n b n int main for int i 1 i n i b i b i 1 b i 求差分陣列的字首和,字首和即為所...