九省聯考 2018 祕密襲擊

題意

給定一顆含 $n$ 個結點的樹,每個點有點權 $d_i$ ,求所有聯通塊中第 $k$ 大之和。

$1\leq n,m,k\leq 1666,1\leq d_i\leq m$ ,時間限制 $5$ 秒。

題解

一道很有趣的題目。

做法簡述:由於 $dp$ 爲卷積形式對其多項式求點值,並通過類似整體 $dp$ 的方式維護變換,再通過拉格朗日插值還原多項式。

由於每次統計 $d_i$ 較難,一個直觀的想法是轉化成 $0/1$ 問題,若答案爲 $d_i$ ,則在 $[1,d_i]$ 均統計一遍。

具體的,答案可以寫成 $\sum_{S} kth(S)=\sum_{S} \sum_{i=1}^n [i\leq kth(S)]=\sum_{i=1}^n \sum_S [i\leq kth(S)]$ 。

那麼對於每個 $i$ ,將點權 $\geq i$ 的設爲 $1$ ,其餘爲 $0$ ,那麼我們只需要知道有多少個聯通塊其點權和 $\geq k$ 。

這是一個簡單的樹形 $dp$ ,根據樹形揹包可得時間複雜度爲 $\mathcal O(nkw)$ 。

據說就過了此題???喜提 $\text{LOJ}$ 最優解,比我的快 $20$ 倍(

我們將 $dp$ 式子寫出,設 $f_{i,j,p}$ 表示當前根爲 $i$ ,且考慮點權 $\geq j$ 的情況時選擇 $p$ 個 $1$ 的聯通塊個數。

也很好轉移
$$
f_{i,j,p}=\prod_{(u,v)} (f_{v,j,c_v}+1) (\sum c_v=p-[d_i\geq j])
$$
由於揹包的實質爲卷積,不妨將該 $dp$ 寫成 $\text{OGF}$ 的形式。


$$
\begin{aligned}
F_{i,j}&=\sum_{p=0}^n f_{i,j,p}\cdot x^p\\G_{i,j}&=\sum_{v\in sub(i)}^n f_{v,j}
\end{aligned}
$$
可得
$$
\begin{aligned}
F_{i,j}&=x^{[d_i\geq j]}\prod_{(u,v)} (F_{v,j}+1)\\Ans&=\sum_{i=1}^{m} \sum_{j=k}^m [x^j] G_{1,i}\\&=\sum_{j=k}^m[x^j] \sum_{i=1}^m G(1,i)
\end{aligned}
$$
顯然這東西不能跑過去。

考慮進一步的優化,由於多項式乘法太慢我們不妨求出 $\sum_{i=1}^m G(1,i)$ 多項式的點值最後在通過拉格朗日插值插回去,那麼我們需要求出 $n+1$ 個點值。

顯然
$$
\begin{aligned}
F_{i,j}(x)&=x^{[d_i\geq j]} \prod_{(u,v)} F_{v,j} (x)\\G_{i,j} (x)&=\sum_{(u,v)} G_{v,j} (x)+F_{i,j} (x)
\end{aligned}
$$
但這還是 $O(nkw)$ 的。(悲

先考慮 $x$ 爲定值且僅有一個的情況。

我們需要維護的操作是維護 $n$ 個關於 $F,G$ 的點值數組。

- 對於新點 $u$ ,$F$ 的前綴賦值爲 $x$ ,後綴賦值爲 $1$ 。$G$ 數組賦值爲 $0$ 。
- 對於 $(u,v)$ ,我們現將 $v$ 的 $F$數組全體加一,然後將兩個 $F$ 數組對應位置相乘,將 $G$ 數組對應位置相加
- 將 $u$ 的 $F$ 數組加到 $G$ 數組上。

注意到這變換是相同的,不妨設計一個變換形式來實現快速轉移。

定義變換 $(a,b,c,d)$ 的作用爲
$$
(a,b,c,d):(f,g)\longrightarrow (af+b,cf+g+d)
$$
容易將上方三個式子寫成相對應的變換,但我們要對於變換實現乘法
$$
(a_1,b_1,c_1,d_1)\cdot (a_2,b_2,c_2,d_2)
$$
這個也很好推
$$
(a_1,b_1,c_1,d_1):(f,g)\longrightarrow (a_1f+b_1,c_1f+g+d_1)\\(a_2,b_2,c_2,d_2):(a_1f+b1,c_1f+g+d_1)\longrightarrow (a_1a_2f+b_1a_2+b_2,(c_2a_1+c_1)f+g+c_2b_1+d_1+d_2)
$$
那麼
$$
(a_1,b_1,c_1,d_1)\cdot(a_2,b_2,c_2,d_2)=(a_1a_2,b_1a_2+b_2,c_2a_1+c_1,c_2b_1+d_1+d_2)
$$
這樣我們就可以知道每個點所對應的變換來快速求出答案了。

但這還是 $\mathcal O(nkw)$ 的。(悲

注意到上述操作很像區間加法,不妨用線段樹支持變換。

具體來講,我們類似打區間 $tag$ ,標記下傳的方式可以得到每個點的變換,而對於合併子樹也類似線段樹合併。

而這個線段樹合併需要支持標記下傳,並且由於變換的乘法沒有交換律我們需要考慮一下非空的子結點是 $u/v$ 。

這個線段樹合併的時/空複雜度也是 $\mathcal O(n\log n)$ 的,因爲標記下傳僅在兩個線段樹的 $\cap$ 下傳,時間複雜度依然是 $\mathcal O(n\log n)$ 的,所以空間複雜度僅多了常數 $(2)$ 倍。

由於我們需要求 $x$ 在 $1\sim n+1$ 的點值需要將上述做法重複 $n+1$ 遍。

即總時間複雜度爲 $\mathcal O(n^2\log n)$ ,但這常數肉眼可見的大,所以被暴力碾了。

https://loj.ac/s/1084408

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