這個方法經常用於這類問題:
給定序列 \(a\),並定義基於序列 \(a\) 的函式 \(f(l, r)\),求 \(\sum\limits_f(l, r)\)。這個方法的核心做用是:
將不滿足可減性的求值,變成只需要可以區間拼合(即滿足區間可加性)的求值式子。拆成每個點的貢獻處理。
從左到右推進端點 \(r\),開乙個資料結構維護對於當前每個 \(l\) 的函式值 \(f(l,r)\),每推進一位 \(r\) 對應了一次的區間修改和一次的整體求和。
etc,這不是本文的重點。
考慮分治:
這回我們只要求跨過中點的區間的貢獻就夠了,即求
\[\sum_^\sum_^f(i,j)
\]這個式子當然還是是 \(o(n^2)\) 的,但是常常它比原問題的那個更加的簡便,有無窮的威力。簡便在哪?簡便在於,本來這個式子可能不滿足區間可減性,但是經過這樣的分治,它只需要區間可加就行了,於是可以轉化為第 ii 節中的方法。
設當前求解當前 \(mid\) 的時間複雜度為 \(o(f(r-l+1))\),那麼總複雜度也就近似的可以認為是 \(o(f(n) \log n\)。
給定數列 \(a\),設 \(f(l,r)=\max\limits_^a_i\),求 \(\sum\limits_^n\sum\limits_^n f(i,j)\)。利用上述轉化後問題就變成了可以用第 ii 部分中的第一種處理,設 \(g(i)\) 為字首/字尾最大值,那麼它一定是單調的,即對於每乙個位置的最大值的貢獻,我就看一下另一邊有多少個數小於它即可。尺取法一下複雜度 \(n\log n\)。事實上還有很多其他解法,這裡只是作為乙個 example。
gsor 1008,謝謝出題人 lxl。
哈哈哈其實他給的做法都是 \(n \log^2 n\) 的,其實很輕鬆可以做到 \(n\log n\),於是就成了最短+最快解(哈哈哈!
一類巧妙利用利用失配樹的序列DP
求長度為 text 的包含給定連續子串 text 的 0 1 串的個數。t 15 通常來說這種題目應該立刻聯想到狀壓 dp 與取反集 這樣就不用考慮大量重複情況的容斥問題。設 f 表示前 i 個字元 最後 t 個字元為 s 不包含給定連續子串的情況數,狀態轉移方程簡單不述。時間複雜度 theta 2...
一類利用佇列優化的DP
這是乙個 o n 2 的狀態和轉移方程 f i,j left f i 1,j 1 k 1 leq j max j 1 end right.這個方程目測是 theta n 2 的,但是實際上,上面的那個方程只是把陣列整體位移了,下面的方程只是在位移後的陣列開端添上了乙個數,這個完全可以通過佇列來實現,...
一類有關序列的技巧問題
問題一 我們有乙個數列a1,a2.an,你如今要求改動數量最少的元素,使得這個數列嚴格遞增。當中不管是改動前還是改動後。每乙個元素都必須是整數。請輸出最少須要改動多少個元素。選取最長的符合要求的序列,然後把其它值改變就可以。怎樣找到符合要求的序列?由於要遞增,所以每乙個數和它自身所在的位置有關,也就...