C++ 基礎(chǔ)算法 - 二維差分
今天學(xué)習(xí)二維差分。

一維差分
在學(xué)習(xí)二維差分之前,先要學(xué)會(huì)?一維差分
這里加強(qiáng)對(duì)一維差分的理解
將一位差分的操作變?yōu)榍熬Y的變化,如下列數(shù)列 ( 從 0 開(kāi)始編號(hào) )
將 2 至 5 的數(shù)字 ( 對(duì)應(yīng)數(shù)列中 7,8,2,1?) 增加 ,且
,那么差分?jǐn)?shù)組從全為 0 變?yōu)?/p>
此時(shí)差分?jǐn)?shù)組的前綴和將分為三段 ( 相較于原來(lái)全為 0 的差分?jǐn)?shù)組?)
第一段為 0 至 1 ( 對(duì)應(yīng)數(shù)列中 9,4 ) 的前綴和不變,仍然為 0
第二段為 2 至 5 ( 對(duì)應(yīng)數(shù)列中 7,8,2,1 ) 的前綴和增加了 4
第三段為 6 至 7 ( 對(duì)應(yīng)數(shù)列中?0,3 ) 的前綴和不變,4 與 -4 相互抵消
正好對(duì)應(yīng)了將 2 至 5 的數(shù)字增加 4 的概念
因此我們可以知道,差分?jǐn)?shù)組中每一位的前綴和表示的就是原數(shù)列該位置的增值
即?,
表示的是差分?jǐn)?shù)組?
的前綴和,轉(zhuǎn)化后可得?
,修指修改后的,原指原來(lái)的
所以每一位的增值?,這就使用數(shù)學(xué)的方法解釋了差分?jǐn)?shù)組的作用,最后我們得到了這樣的式子
這樣看起來(lái)差分的復(fù)雜度只有一次修改的復(fù)雜度??,修改
次,復(fù)雜度也僅有
次,看起來(lái)時(shí)間復(fù)雜度十分好,但是如果算上查詢
?次,復(fù)雜度變?yōu)?
,并不高效
因此差分僅適合在數(shù)據(jù)范圍較小的題目使用,遇到數(shù)據(jù)范圍更加大的題目時(shí)就需要使用復(fù)雜度為??的樹(shù)狀數(shù)組和線段樹(shù)來(lái)實(shí)現(xiàn)了,但因?yàn)椴罘志幋a簡(jiǎn)單,在適合的時(shí)候往往選擇容易編寫(xiě)的差分

二維差分
由一維差分可以知道,二維差分就是選擇一個(gè)矩形區(qū)域,將區(qū)域內(nèi)的所有元素增加或減少一個(gè)數(shù)?
簡(jiǎn)單做法 ( 并不正確 )
本段通過(guò)思考簡(jiǎn)單的做法推動(dòng)二維差分實(shí)現(xiàn),因此本段不是正解,可以選擇性閱讀本段
修改
先考慮將矩形區(qū)域處理一下,變?yōu)橐粭l條數(shù)列的區(qū)間從而使用普通一位差分修改

如上圖,將??至
?的值加上?
,再將?
至?
修改為?
,復(fù)雜度為?
查詢
在查詢時(shí),如果詢問(wèn)的矩形區(qū)域 (??) 正好沒(méi)有與修改矩形區(qū)域 (?
),的左邊線 (?
) 相交,這時(shí)在統(tǒng)計(jì)時(shí)就無(wú)法加上修改矩形區(qū)域修改的值,因此,我們不能從詢問(wèn)的矩形區(qū)域的左邊線 (?
),開(kāi)始計(jì)算,應(yīng)該從其對(duì)應(yīng)在?
?軸上的點(diǎn)?
與?
開(kāi)始計(jì)算
這種方式將每一行都看做一個(gè)差分?jǐn)?shù)組,都做了一次差分,時(shí)間復(fù)雜度為?

不難發(fā)現(xiàn),這種方法的時(shí)間復(fù)雜度比較劣,還有提升的空間
正確做法
本段講解的才是正確的二維差分
修改
我們嘗試將修改操作的復(fù)雜度降至?,我們知道一維差分可以將所有?
?(?
?) 的數(shù)值增加
,通過(guò)兩次修改實(shí)現(xiàn)區(qū)間修改

將這個(gè)思想推廣至二維,那么二維差分就應(yīng)該可以將所有? (?
) 的數(shù)值增加?
例如上面三連展示的圖片,我們將右下角看做原點(diǎn),?是要修改的矩形區(qū)域,這時(shí)候我們將上一段所述的?
,那么點(diǎn) B 左上的所有點(diǎn)都增加了
,但是我們更改的目標(biāo)是?
,如果使用上述方法將會(huì)更改整一個(gè)?
,而如果要消除影響,就可以將?
?再次減去
看看這個(gè)多邊形的樣子,是不是很熟悉
所以,我們以右上角為原點(diǎn)并加入二維前綴和的思想,并利用公式
上述公式在?二維前綴和?中講過(guò)了
這時(shí)候我們需要反過(guò)來(lái)使用,因?yàn)槲覀兿葎?chuàng)造了 的影響 ( 增加?
),所以我們?cè)诤竺鎸⑾溆绊懀涂梢允褂眠@個(gè)式子,?
這三個(gè)項(xiàng)就是消除的關(guān)鍵,因?yàn)樵黾恿?,所以?
?的值也就為
,因此?
與?
都要等于?
?以消除影響,但是我們發(fā)現(xiàn)
被兩次操作都減了一次
,因此需要在?
?再加上一次
,這其實(shí)就是前綴和的思路
由此,我們就用??的時(shí)間復(fù)雜度記錄了差分的影響,代碼實(shí)現(xiàn)如下 (?這里我們將左上角看做原點(diǎn) )
查詢
通過(guò)修改操作修改了差分的影響,我們發(fā)現(xiàn)在圖上任意一點(diǎn),其差分?jǐn)?shù)組的二維前綴和就是其修改的值
因此我們就需要計(jì)算差分的前綴和,下面展示的是單次查詢
如果全部修改好后進(jìn)行一次查詢可以這么寫(xiě) ( 其實(shí)沒(méi)什么區(qū)別 )
二維差分的代碼并不難,較難得地方在于需要一些思考

好了那么這篇文章就講到這里了,如果你覺(jué)得本文對(duì)你有所幫助的話,請(qǐng)不要忘記三連支持!
鴿了好久...