線性dp之最大子段和問題小結

子段和問題

我們知道線性dp中一道典中典的題目就是求最大子段和;

狀態方程爲:dp[i]=max(dp[i]+a[i],a[i]);

當然這只是最基礎的,還有很多擴展;

  1. 子段長度不大於m的最大子段和
    這個時候dp已經不好用了,可以考慮前綴和sum[i],維護min(sum[k])(i-m<=k<i),然後只要sum[i]-sum[k]就可以了,具體怎麼維護可以單調隊列(模板題);

  2. 子段長度不小於m的最大子段和
    (1)第一種方法,先用dp計算一次沒有長度限制的最大子段和,然後
    f[i]=dp[i-1]+sum[i+m]-sum[i-1],最後對每一個f[i]求一個max;這個就是相當於在每個dp[i-1]後面加一個長度爲m的段;
    (2)直接維護min(sum[k])(1<=k<=i−m),這個維護就不要單調隊列,直接一遍循環維護就行;

  3. 環狀最大子段和
    (1)破環爲鏈(長度擴大兩倍),然後維護一個長度不大於m(m爲環的長度)的最大子段和
    (2)這種方法在後面求兩段和也要用到,非常重要;
    就是考慮這個子段是否經過連接點(就是同時經過a[1]和a[n]),如果經過,可以求1-n的最小子段和,然後總和減去這個最小子段和;如果不經過,就直接求1-n的最大子段和就可以;

  4. 環狀最大兩段子段和
    就是第3種的一個擴展,求兩段,只要正向反向維護一個最大子段和就可以;
    具體講一下,爲什麼經過連接點要那樣算?
    可以發現環狀的最大子段和要不就是-----++++ ----++++ ----(把環拆成鏈,長度沒有擴大兩倍,加號代表該位置取,減號代表不取),要不就是++++ ------++++ ----+++,也就是說要不就經過連接點,要不就不經過;
    如果不經過,那麼和普通的線性沒區別;如果經過,那麼就有三段子段和,不好求,正難則反,所以只要求最小子段和就可以了;
    題目:洛谷·P1121 環狀最大兩段子段和

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章