差分、字首和有著特殊的關係,也是一種入門演算法
首先考慮這樣乙個問題:字首和想必大家都知道,給定一陣列有 n 個的正整數放到陣列 a 裡,現在要求乙個新的陣列 b,新陣列的第 i 個數 b[i]是原陣列 a 第 0 到第 i 個數的和。
c[i]
,用另外一陣列sum[n]
來儲存c[1]-c[n]
的和,這樣在求任意區間的和的時候,就非常的快捷了
具體遞推為
sum[i] = c[i-1]+c[i]
什麼是差分?
差分是兩個元素的差值,我們用乙個新的陣列a[i]
記錄差分的值,陣列 a 叫做差分陣列
具體遞推為
a[i] = c[i]-c[i-1]
字首和陣列sum
差分陣列a
差分陣列a
的字首和是原陣列
字首和sum
的差分陣列是原陣列
在實際的應用當中,對乙個陣列進行操作時,進行區間增加或者減少同樣的數值,就可以直接在差分陣列上進行修改,下次在查詢某個點的值就可以通過差分陣列的來求,十分的快捷
現在有這樣乙個問題
給定乙個n*m大小的矩陣a,有q次詢問,每次詢問給定x1,y1,x2,y2四個數,求以(x1,y1)為左上角座標和(x2,y2)為右下角座標的子矩陣的所有元素和,包括左上角和右下角的元素。像這樣的題目,我們首先想到的就是遍歷求和,但是如果時多組輸入的話,每次都一遍一遍的計算,很容易tle,所以我們可以在原陣列的基礎上構造二維字首和陣列,求解的話就可以比較快了
如何構造二維字首和陣列?
二維陣列的每個點等於其左邊的點+上邊的點-左上方的點
,如果存在就計算,不存在則不計算,比如在邊界上~
在這個圖里,a = b+c-d + a
因為 b 和 c 中都加了一遍d,所以根據容斥原理,把多加的減掉
假如我想求a[2][4]的字首和,我得先加上a[1][4]的字首和,再加上a[2][3]的字首和,然後這個時候我們發現實際上a[1][3]這個部分我們加了兩遍,所以我們需要再減去一遍a[1][3],於是得出公式a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1]。
完整**
#include
using
namespace std;
const
int maxn=
1e3+9;
int a[maxn]
[maxn]
;int
main()
for(i=
1;i<=n;i++
)for
(i=1
;i<=q;i++
)}
例題
最高的牛
題意很簡單,我們可以知道一點,在給出的相互能看見的牛對形成的區間是不會交叉的,因為每對牛中間的牛都比他們低
思路:如果兩頭牛看得見則中間的牛h-1,同時使用差分記錄,最後再字首和還原陣列。
#include
using
namespace std;
const
int n =
1e4+10;
int s[n]
;//記錄差分
bool flag[n]
[n];
//此處用int會超記憶體 int是4 個位元組32位,bool只有1位
intmain()
}for
(int i =
1; i <= n; i++
)return0;
}
洛谷字首和例題 字首和 差分詳解及經典例題補充
目錄 字首和 與 差分可以理解為互逆的 求字首和 跟 差分通常設陣列首項下標為1,方便思考的計算。對於一維陣列 a n 存在陣列 sum n 使得 sum i a 1 a 2 a i 以o 1 的時間複雜度得到某塊區間的總和 舉個例子 輸入乙個長度為 n 的整數序列。接下來再輸入 m 個詢問,每個詢...
字首和 差分總結
差分問題總結 一維例題 輸入乙個長度為n的整數序列。接下來輸入m個操作,每個操作包含三個整數l,r,c,表示將序列中 l,r 之間的每個數加上c。請你輸出進行完所有操作後的序列。設那麼求a陣列時,就可以利用b陣列的字首和來計算 在a2 a4區間內每個數加x,就相當於b2加上2,而b3不變,b4也不變...
字首和 差分
數列的字首和 sum i 表示a 1 a i 的和 用處1 求i j的和sum j sum i 1 用處2 區間修改。設定乙個change陣列。當區間 i,j 上要加k時,我們令change i k,令change j 1 k。如果我們對change陣列求字首和的話,字首和sum change i ...