1. 程式人生 > >動態dp學習筆記

動態dp學習筆記

\(noip\)考了,趕緊補一發。

不得不說網上的題解還是不錯的ljq的程式碼吼啊

  • 一開始看的部落格
  • 模板
  • 其實我感覺看部落格不如看別人優秀的程式碼來的快

    首先是樹鏈剖分的思想

  • 講一講自己的感想
  • 首先我們為了使得\(f\)帶修改,引入了樹鏈剖分套線段樹維護矩陣進行\(dp\)
  • 但是這樣我們是無法直接維護\(f\)的,因為剖分的思想是重鏈不會超過\(log\)次劃分。
  • 假設我們現在可以一次性跳完整個重鏈,那麼問題就變成了是否可以從重鏈頂跳到上一個重鏈
  • 於是我們引入新陣列\(g\),表示不算當前重鏈的所有貢獻。
  • 那麼我們只需要維護\(g\),每次修改就直接把整個重鏈的\(g\)
    全部\(\prod\)起來,然後修改父親的\(f\)
  • 此時我們發現,不是每個地方的\(f\)都是有意義的。
  • 首先我們知道每個位置的\(g\),然後用線段樹維護他。
  • 維護\(g\)的原因是我們可以通過線段樹優化\(dp\)轉移使得在\(log\)的時間內得到一段的\(g\)卷積。
  • 所以我們只知道每個鏈頂的\(f\)值,而並不關心每個點的\(f\)
  • 那麼問題就簡單多了,對於每次修改,我們只需要修改當前點的\(g\),然後\(\prod\)到鏈頂的\(f\),再用當前的\(f\)更新父親的\(g\),重複這個操作。
  • 實際上我們又給出了\(f\)的新定義,即\(f=\prod g\)
    .
  • 總結一下就是:
  • 個人認為動態\(dp\)的思想在於整體考慮一整個重鏈的\(dp\)轉移
  • 然後再把這個重鏈的\(dp\)轉移貢獻給鏈頂父親
  • 那麼在實際設計狀態的時候,形如\(g_{i,j}\)表示\(i\)點不考慮重兒子的\(dp\)值。
  • 然後根據狀態轉移方程一次性考慮一整個重鏈
  • 這樣的話,我們在修改操作的時候,就只需要考慮鏈與鏈之間的關係了。
  • 至此,我們得到了一個\(O(4*q*log^2n)\)的做法。

    但是這樣還是不夠優秀

  • 晚上更。