单调队列优化和决策单调性优化
前言:dp蒟蒻拼命挽救一下dp a....,會圍繞三個“形如”來寫...但更重要的是本質理解啊qwq
A.單調隊列優化:
有時狀態轉移方程形如f[i][j]=min{f[i-1][k]}+w(i,j),其中l(i,j)<=k<=j,l(i,j)<=l(i,j+1)。 如果兩個決策k1,k2滿足f[i-1][k1]<=f[i-1][k2]且k1>k2,那么k1出現后k2就沒用了。 維護一個隊列,按k從小到大存下所有有用的決策,f[i-1][k]是單調上升的。 每次加入新決策時,從隊列末尾刪去沒用的決策。 當隊列開頭決策的k<l(i,j)時將它刪去。(emmmmmmm這個海星,在單調性滿足情況下用單調隊列留下靠后的且較優的)
B.決策單調性優化:
首先對于所有的疑似決策單調性優化的題,最好是用打表來證明(隨便搞個大樣例或者后頭對拍一下.....一般嚴謹證明不太現實,當然也可以)這個在打O(N^2+)暴力時順便記錄一下gi就行了(這里gi指是從gi轉移到i的)[最好考試都要先打好暴力,然后對著暴力來想a,分析性質]
這里主要介紹兩種實現:
1.二分實現:
首先是講稿上的一些說法:
有時狀態轉移方程形如f[i]=min{f[j]+w(j,i)},其中j<i。 記g(i)表示f[i]取到最優值時的決策點j,如果g(i)<=g(i+1),我們可以用單調性優化dp。 同樣用一個單調隊列存下有用的決策,對于相鄰兩個決策k1<k2,我們二分求出k2比k1優的時間t(k1,k2)。加入一個新決策時,假設新決策為k3,末尾兩個決策為k1,k2。如果t(k2,k3)<=t(k1,k2),那么可以刪去k2。 轉移時如果開頭的決策已經不優了就刪去它。
接下來補充一點自己理解的具體實現:
首先,對于所以的gi可以先標記為1(0)[視題目而定]默認為全都為從1轉移過來的,這里用一個結構體的棧來維護每個單調決策的適用范圍。
然后,我們依次考慮往后的單調決策更新,那么對于每個i我們先通過二分已經維護的單調決策的適用范圍可以算出f[i](用線段樹啥的來刷一遍gi有點太傻了a....)同時由此我們可以得出復雜度為O(nlogn)(因為二分嘛)。
現在我們得到了新的f[i],所以用它來更新以后的,由于單調性,我們可以從后往前掃描棧,這里有兩種情況:
(1)如果這個老決策的作用區間的起始位置(即L)仍然不如新決策優,那么我們彈出老決策,將老決策的作用區間整個合并到新決策中,繼續往前掃 ;
(2)如果不滿足前面的條件,在老決策的作用區間中二分出新決策起作用的起始位置,將老決策分割,新決策入棧,結束掃描過程?;
這里每個決策里的二分就是對于當前的m判斷f[i]+w[i,m]和f[j]+w[j,m]誰更優,若更優則i的起始范圍往前移,否則往后移;
感覺這個二分實現還挺好想的a....(霧)而且適用范圍貌似要比分治實現更廣一些(聽分治實現的時候一臉懵a...)
在這里推薦一道例題(實打代碼才有效)
bzoj4709: [Jsoi2011]檸檬?
以及代碼(咕咕咕):
?
2.分治實現:
首先依舊是講稿上的一些說法:
有時狀態轉移方程形如f[s][i]=min{f[s-1][j]+w(s,j,i)},其中j<i,且g(s,i)<=g(s,i+1)。 如果w(s,j,i)不能很快算出,之前的方法就不再適用了。 假設i的取值范圍是[l,r],取m=(l+r)/2。我們可以先求出g(s,m),然后遞歸處理[l,m-1]和[m+1,r]。
接下來依舊是補充一點自己理解的具體實現:
(咕咕咕)
轉載于:https://www.cnblogs.com/degage/p/9741156.html
總結
以上是生活随笔為你收集整理的单调队列优化和决策单调性优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python函数里面,一个*是可变参数的
- 下一篇: 手把手教你使用CocoaPods管理你的