題解 P5566 【[SDOI2008]紅黑樹】
阿新 • • 發佈:2020-11-26
最近在刷平衡樹,看到標題就進來了,沒想到是個dp???看了看,發現可以貪心,於是就有了這篇題解。
分析:
因為紅黑樹本身的性質,所以我們可以通過畫圖來列舉所有情況:
先把每一個節點看成黑色的,通過紅黑樹性質來把一些結點變成紅色的。
- \(case1:\)
如圖:
最虧的一種情況,兩個黑色節點沒變出來一個紅色節點。
- \(case2:\)
如圖:
三個黑色節點變成一個紅色節點,有點浪費。
- \(case3:\)
如圖:
此時四個黑色節點變成兩個紅色節點,黑色節點的利用率最大。
所以,貪心就很明確了。
\(\text{code:}\)
#include "cstdio" int n, ans, k; int main() { scanf("%d", &n); k = n + 1; while (k > 1) { ans += k & 1; k >>= 1; } printf("%d\n", ans); k = n + 1; ans = 0; while (k > 1) { if (k == 2) ans++, k--; else if ((k & 3) == 1) ans += ((k >> 2) << 1) - 1, k >>= 2, k++; else if ((k & 3) == 2) ans += ((k >> 2) << 1), k >>= 2, k++; else if ((k & 3) == 3) ans += ((k >> 2) << 1) + 1, k >>= 2, k++; else ans += (k >> 1), k >>= 2; } printf("%d", ans); return 0; }
關於DP
自己想了一種方法,不過好像有億點點慢。
以最小值為例:
用 \(R_{(i,j)}\) 表示 \(i\) 個結點,黑高度為 \(j\) 的紅根樹中紅色結點最小值;
\(B_{(i,j)}\) 表示 \(i\) 個結點,黑高度為 \(j\) 的黑根樹中紅色結點最小值。
\(\therefore R_{(i,j)}=\min\left({R_{(i,j)},B_{(k,j-1)}+B_{(i-k-1,j-1)}+1}\right)\quad(i\leq k\leq i-2)\);
\(\therefore B_{(i,j)}=\min\left({B_{(k,j-1)},B_{(i-k-1,j-1)},R_{(k,j)}+R_{(i-k-1,j)},R_{(k,j)}+B_{(i-k-1,j-1)}}\right)\quad(i\leq k\leq i-2)\)