[動態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標記。
[動態dp]線段樹維護轉移矩陣