1. 程式人生 > >[LOJ#2473][九省聯考2018]祕密襲擊(樹形DP+生成函式+線段樹合併+拉格朗日插值)

[LOJ#2473][九省聯考2018]祕密襲擊(樹形DP+生成函式+線段樹合併+拉格朗日插值)

Address

洛谷P4365
BZOJ5250
LOJ#2473

The First Step - 轉化

簡版題意:給定一棵點帶權樹,求樹上所有大小大於 k k 的連通塊的第 k k 大值之和。
眾所周知,「第 k

k 大值」和「值 x x 的排名」可以互相轉化。
所以,答案為:
i =
1 W ( i k
) × i \sum_{i=1}^W(i的排名為k的連通塊個數)\times i

The Second Step - DP狀態

如何求出「 i i 的排名為 k k 的連通塊個數」?
如果權值互不相同,那麼 i i 的排名為 k k 的連通塊個數就是「滿足 i \ge i 的權值有 k k 個的連通塊個數」。
如果權值有相同,那麼 i i 的排名為 k k ,就必須保證 i \ge i 的權值個數至少 k k ,但 i + 1 \ge i+1 的權值個數又要小於 k k
於是 i i 的排名為 k k 的連通塊個數為「 i \ge i 的權值個數 k \ge k 的連通塊個數」 - i + 1 \ge i+1 的權值個數 k \ge k 的方案數」。
設狀態 f [ u ] [ i ] [ j ] f[u][i][j] 表示 u u 為根的連通塊(包含空連通塊), i \ge i 的權值個數為 j j 的方案數。
這樣,答案就為:
i = 1 W i j = k n { u = 1 n f [ u ] [ i ] [ j ] u = 1 n f [ u ] [ i + 1 ] [ j ] } \sum_{i=1}^Wi\sum_{j=k}^n\{\sum_{u=1}^nf[u][i][j]-\sum_{u=1}^nf[u][i+1][j]\}
= u = 1 n i = 1 W j = k n f [ u ] [ i ] [ j ] =\sum_{u=1}^n\sum_{i=1}^W\sum_{j=k}^nf[u][i][j]

The Third Step - DP轉移

關於連通塊計數的樹形 DP 是一個經典模型。
邊界:
f [ u ] [ i ] [ 1 ] = { 1 i d u 0 i > d u f[u][i][1]=\begin{cases}1&i\le d_u\\0&i>d_u\end{cases}
f [ u ] [ i ] [ 0 ] = { 0 i d u 1 i > d u f[u][i][0]=\begin{cases}0&i\le d_u\\1&i>d_u\end{cases}
轉移時列舉 u u 的子節點 v v 並列舉 v v 的子樹包含的連通塊大小 h h
f [ u ] [ i ] [ j ] = h = 0 j f [ u ] [ i ] [ j h ] × f [ v ] [ i ] [ h ] f[u][i][j]=\sum_{h=0}^jf'[u][i][j-h]\times f[v][i][h]
f f' 為向 v v 轉移之前的 DP 陣列。
最後加上空連通塊:
f [ u ] [ i ] [ 0 ] + + f[u][i][0]++
由於第三維的上界只有 u u 的子樹大小,所以每對點都在 LCA 處貢獻 W W 次,
複雜度 O ( n 2 W ) O(n^2W)
據說很多人用這種做法水過並跑得比標解快

The Fourth Step - DP優化

既然沒人寫正解,我就來水一發
發現 f f 向子樹的轉移是一個卷積的形式。所以考慮生成函式
F [ u ] [ i ] F[u][i] f [ u ] [ i ] [ j ] f[u][i][j] 的生成函式:
F [ u ] [ i ] ( x ) = j