[動態dp]線段樹維護轉移矩陣


背景:czy上課講了新知識,從未見到過,總結一下。

所謂動態dp,是在動態規划的基礎上,需要維護一些修改操作的算法。

 

這類題目分為如下三個步驟:(都是對於常系數齊次遞推問題)

1先不考慮修改,不考慮區間,直接列出整個區間的dp方程。這個是基礎,動態dp無論如何還是dp(這一步是一般是重點)

2.列出轉移矩陣。由於有很多修改操作,我們將數據集中在一起處理,還可以利用矩陣結合律,並且區間比較好提取,(找一段矩陣就好了),修改也方便。

3.線段樹維護矩陣。對於修改,我們就是在矩陣上進行修改,對於不同的題目,我們要用不同的修改方式,和記錄手段。但是都是線段樹一個節點維護的是這個區間內矩陣的信息。如矩陣乘積,矩陣和等等。線段樹的區間優勢,可以應對區間修改問題。

T1:HDU5068

 

這里,由於是單點修改,所以直接到葉子節點,修改后再pushup就可以了。

線段樹維護區間內矩陣乘積。

 

 

T2:CF  Sasha and Array

就是斐波那契數列。

這里的可以原因是:提出B,因為矩陣右分配律,再提出一個M^x,還是矩陣右分配律。注意這里M^x,B是不能交換順序的。但是M^x放在求和的前邊乘,還是后邊乘是無所謂的。因為都是M

可以用左分配律,也可以用右分配律。

其實代碼不難想。

1.laz標記應當建一個和t[4*N]一樣的laz[4*N],這樣,每個結構體只存一個矩陣a,不但節省空間,而且內置函數的矩陣乘法還方便,因為無論如何都轉移到a矩陣,而不用考慮是a乘laz還是laz乘laz。

2.數組越界了,被卡了很長時間。開a[3][3]就可以,沒有發現的原因是,c++本地編譯不會RE,放到CF上就會出現奇怪答案,而且莫名有的地方數組內的值就變了,比如說突然都變成0

3.注釋不要太多,以免掩蓋正解,導致把laz 下放注釋掉了。。。

 

 

T3:

本質不同:不一樣。長度不同,或者長度一樣對應位置數字不全一樣。

注意是子序列不是子串

注意,為什么用f[i][0/1]?因為當最后一位不一樣時,這兩個子序列一定不一樣,所以f[i-1][0]和f[i-1][1]中的每一個都是不一樣的。

並且,這還跟原數組數值0/1掛鈎,很好聯系上了。

加的一個1是就取這一位,其實是之前每一個都多了一位,就沒有了最初的長度為一的子序列。所以加上。

也就是說,區間矩陣乘積結果的矩陣可以直接進行翻轉,先翻再乘,和先乘再翻沒區別。

直接正常維護就好,加一個rev標記。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM