序列 DP

2huk發表於2024-03-13
  • LOJ P507

  • \(n\) 張牌排成一排,每張牌有屬性 \((c_i, v_i)\)。保證 \(c_i \le k\)

    每次操作選擇兩張牌 \(l, r\) 滿足 \(c_l = c_r\),刪除 \(l \sim r\) 中的所有牌,並獲得 \(\sum_{i=l}^rv_i\) 的收益。

    求最大的收益。

  • \(n, k \le 10^6\)

設狀態 \(f_i\) 表示若只考慮前 \(i\) 張牌,能獲得的最大收益。

轉移列舉第 \(i\) 張牌是否是在最後一次操作中被刪,以及被哪個區間刪。即 \(f_{i - 1}\)\(\max_{j=1}^{i - 1}\{f_{j - 1} + \sum_{k=j}^iv_k \mid c_i = c_j\}\) 的較大值。

直接做是 \(n^3\) 的。區間求和那個部分可以字首和最佳化,但仍然是 \(n^2\) 的,即 \(\max_{j=1}^{i - 1}\{f_{j - 1} + \sum_{k=1}^iv_k - \sum_{k=1}^{j-1}v_k \mid c_i = c_j\}\)

可以把與 \(j\) 無關的提到外面,即 \(\sum_{k=1}^iv_k + \max_{j=1}^{i - 1}\{f_{j - 1} - \sum_{k=1}^{j-1}v_k \mid c_i = c_j\}\)

然後這個就很好維護了。我們用桶維護每個 \(c_i\) 所對應的最大的 \(f_{i-1} - \sum_{k=1}^{i-1}v_k\),轉移可以最佳化成 \(\Theta(1)\)。總時間複雜度 \(\Theta(n)\)


  • P4342 [IOI1998] Polygon

  • 有一個 \(n\) 個頂點 \(n\) 條邊的環,頂點上有數字,邊上有 \(+, \times\) 兩種運算子號。

    首先刪掉一條邊,然後每次選擇一條連線 \(V_1, V_2\) 的邊,用邊上的運算子計算 \(V_1\)\(V_2\) 得到的結果來替換這兩個頂點。

    求最後元素的最大值。

  • \(n \le 50\)

顯然區間 DP。首先倍長破環為鏈。

設狀態 \(f_{l, r}\) 表示將區間 \(l \sim r\) 內的數字處理後得到的最大數字。轉移列舉斷點 \(k\),即 \(f_{l, r} = \max_{k=l}^{r-1} \operatorname{opt}(f_{l, k}, f_{k + 1, r})\),其中 \(\operatorname{opt}\) 表示邊上的運算子號。

這樣做是不正確的。注意到兩個負數相乘結果為正數,所以再維護 \(g_{l, r}\) 表示最小值。轉移類似。

複雜度 \(\Theta(n^3)\)

相關文章