本文為 @A_zjzj《dp 專題》學習筆記。
轉移性質
Lanterns
題意:\(n\) 個燈籠拍成一排,第 \(i\) 個燈籠具有 \(p_i\) 的亮度。每個燈籠要麼朝向左照亮 \([i - p_i, i - 1]\),要麼朝向右照亮 \([i + 1, i + p_i]\)。
尋找一種方案,為所有的燈籠定向,使得每一個燈籠被至少一個其他燈籠照亮。\(2 \le n \le 3\times 10^5, p_i \in [0, n]\)。
設 \(f_i\) 表示前 \(i\) 盞燈能覆蓋的最長字首,考慮幾種轉移:
- 前 \(i - 1\) 盞燈能覆蓋 \(i\),\(f_i \gets \max(f_{i - 1}, i + p_i)\)。
- 前 \(i - 1\) 盞燈不能覆蓋 \(i\),先把 \(i\) 忽略,之後再定向,\(f_i \gets f_{i - 1}\)。
- \(i\) 向左覆蓋,存在一個 \(f_j + 1 \ge i - p_i\),所有 \((j, i)\) 的燈向右定向,\(f_i \gets \max(i - 1,\ j + 1 + p_{j + 1}, \cdots, i - 1 + p_{i - 1})\)。
顯然有 \(f_{i - 1} \le f_i\),二分 \(j\),樹狀陣列維護字尾最大值。submission
來源不明的一道題
題意:給出 \(n\) 和 \(a_{2 \sim n}, b_{2 \sim n}\),表示 \(i\) 有單向邊連向 \([a_i, i - 1]\),\([b_i, i - 1]\) 有單向邊連向 \(i\),邊權為 \(1\)。
設 \(d(i, j)\) 表示 \(i\) 到 \(j\) 的最短路,求 \(\bigoplus_{i, j} d(i,j) \times (i + j)\)。\(1\le n\le 6000,\ a_i < i,\ b_i < i,\ \text{1s}\)。
如果從 \(i\) 向左走一步到 \(j\),緊跟著向右走到 \(k\),這是一定不優的:
- \(k \le i\),顯然有 \(a_i \le j < k \le i\),可以一步或零步走到。
- \(k > i\),\(j\) 能一步到 \(k\),說明 \(b_k \le j\),說明 \(i\) 也能一步到 \(k\)。
因此最優方案一定是先向右走若干步,再向左走若干步。
列舉起點 \(s\),設 \(f_i\) 表示 \(s\) 到 \(i\) 的最短路,分兩部分轉移(從前往後掃一遍,再從後往前掃一遍):
第一部分:\(f_i \gets f_j + 1,\ b_i \le j < i\);第二部分:\(f_i \gets f_j + 1,\ a_j \le i < j\)。可以線段樹做到平方對數。
以向右的轉移為例,如果 \(i < j\land f_i \ge f_j\),\(f_i\) 顯然不優。
設 \(g_x = \max_\limits{j < i\land f_j = x} j\),表示值為 \(x\) 時的最優決策點,顯然 \(f_i\) 的上界為 \(x = f_{i - 1} + 1\)。不斷使 \(x \to x - 1\),直到 \(g_{x - 1} < b_i\)。
用 \(x\) 更新 \(f_i\),並使 \(g_x = i\)。上述做法依賴於 \(g_0\sim g_{f_{i - 1}}\) 是單調遞減的,可以歸納證明。勢能增量 \(O(n)\),複雜度 \(O(n)\)。
對於向左的轉移,如果 \(a_i \le a_j \land f_i \le f_j\),\(f_j\) 顯然不優。設 \(g_x = \min\limits_{j > i \land f_j = x} a_j\)。
\(f_i\) 的上界是 \(\min(f_i, f_{i + 1} + 1)\),不斷使 \(x \to x - 1\),直到 \(g_{x - 1} > i\),歸納證明 \(g_0 \sim g_{f_{i + 1}}\) 是單調遞增的。
時間複雜度 \(O(n^2)\)。submission
一類特殊題型
求一個排列 \(\{p\}\),最小(大)化如下值:
其中 \(f(i, j)\) 如下:
考慮按照 \(p_i\) 的大小,從小到大插入序列的過程,維護若干連續段(只是說明某些元素在最終排列上連續,並沒有確定位置)。
每次插入有以下情況:
- 將兩個連續段合併成一個。
- 插入一個連續段的左邊/右邊。
- 新增一個連續段。
由於保證了插入順序,容易算出每個元素的貢獻。另外,需要維護連續段個數,保證最終連續段合併成一個。
可能需要判斷插入時是否插在全域性的開頭或末尾。
Ant Man
題意:給定排列 \(\{p\}\) 的第一個元素 \(s\) 和最後一個元素 \(e\),找出一個排列,最小化:
其中,\(2\le n \le 5000,\ x_1 < x_{2} < \cdots < x_n\)。
和原模型基本一致,\(f(i, j)\) 表示插入前 \(i\) 個數,分成 \(j\) 個連續段的最小代價。
注意 \(s, e\) 沒有合併連續段的轉移,\(s\) 只算右邊貢獻,\(e\) 只算左邊貢獻,\(s\) 所在連通塊不能右插,\(e\) 不能左插。
新增一個 \(i\) 作為連通塊時,需要滿足 \(j - [i > s] - [i > e] \ge 1\),否則無法新增。submission