原文:原文連線
類似於數學中的求導和積分,差分可以看成字首和的逆運算。
差分陣列:
首先給定乙個原陣列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 求差分陣列的字首和,字首和即為所...