LOJ3053 十二省聯考2019 但願 容斥、樹形DP、長鏈剖分

傳送門數組


官方題解其實講的挺清楚了,就是鍋有點多……優化

一些有啓發性的部分分

L=N

一個經典(反正我是不會)的容斥:最後的答案=對於每一個點可以以它做爲集合點的方案數-對於每條邊可以以其兩個端點做爲集合點的方案數。緣由是:對於每一種合法方案,集合點必定是樹上的一個連通塊,知足$n=m+1$。算點時,這種方案被算了$n$次;算邊時,這種方案被算了$m=n-1$次,因此每個方案都剛好被算了一次。spa

有$DP$:設$f_i-1$表示選擇了包含$i$和$i$的子樹中的點的一個連通塊的方案數,轉移枚舉每個兒子選不選。而後設$g_i$表示以$i$爲原樹的根,選擇了包含$i$和$i$的子樹中的點的一個連通塊的方案數,這個在求完$f$以後換根DP,換根的時候能夠同時計算出每條邊的方案。調試

NL較小

改一下$N=L$的DP:設$f_{i,j}-1$表示選擇了包含$i$和$i$的子樹中的點的一個連通塊,其中距離$i$點最遠的點與$i$距離$\leq j$的方案數,$g_{i,j}$表示以$i$爲原樹的根,選擇了包含$i$和$i$的子樹中的點的一個連通塊,其中距離$i$點最遠的點與$i$距離爲$\leq j$的方案數。blog

一樣能夠求完$f$後換根DP求$g$,可是有個問題:如何從$f_{fa_x}$中去掉$f_x$的貢獻。能夠在計算$f$的時候計算每個點合併全部孩子的一個前綴的答案、合併全部孩子的一個後綴的答案,這樣把一個前綴和一個後綴拼起來就能夠獲得去掉$f_x$的貢獻的$f_{fa_x}$。遞歸

##鏈get

枚舉一下點和邊,方案數能夠直接算同步

52pts代碼io

k=1

能夠枚舉選擇的連通塊的根,用長鏈剖分+線段樹優化,與正解關係不大因此略過打包

正解

從$NL \leq 10^7$開始。稍微修改一下$g_{i,j}$的定義:設$g_{i,j}$表示選擇$i$、不選擇$i$的子樹,選擇的連通塊中最大距離$\leq j$的方案數。

f的優化

注意到$f$能夠長鏈剖分優化。在長鏈剖分的轉移中咱們須要支持後綴乘(由於後綴有一段要乘的值相同)、總體加(轉移完成以後全部$f_{i,j}$須要$+1$),能夠給長鏈剖分打乘法標記$a$和加法標記$b$解決,一次後綴乘就把前面沒有乘的部分乘上逆元。可能會有乘$0$的問題,因此還須要一個後綴賦值標記,當乘$0$時把當前的後綴賦值爲$-\frac{b}{a}$。

g的優化

$g$是一個換根DP,可是也能夠用長鏈剖分優化。將重鏈和輕邊的轉移分開考慮:①對於重鏈直接暴力將輕兒子的$f$值轉移過來,複雜度跟長鏈剖分同樣;②對於輕邊,假設這條輕邊轉移到的點$x$的子樹深度爲$p$,那麼由於在最後統計答案的時候只須要每一個點的$g_{x,L}$,因此$x$子樹中只有$g_{x,j}(j \in [L - p , L])$有用,能夠只轉移這一些值。那麼每一條輕邊就只會轉移輕子樹深度個$g$,總複雜度也是均攤$O(n)$的

g的轉移時的一個問題

咱們還須要解決在轉移$g$的過程當中要取孩子的一個前綴和一個後綴的問題。能夠主席樹可是$O(nlogn)$有點慢。考慮按照求$f$時DFS順序的反序DFS求$g$,咱們到達一個點、即將遞歸到下一個點的時候,將這個點對於當前點的$f$的貢獻消除,這樣能夠獲得前綴的值,再拿另外一個數組維護一下後綴的$f$值就能夠獲得前綴和後綴。支持撤銷只須要在每一次從輕邊修改一個點時把全部標記和將要修改的位置的值記錄下來打包丟到一個棧裏面。

線性求逆元

有一個預處理逆元的科技:可知要求逆元的數必定是$f_{x , p}$,其中$p$是$x$的子樹大小,因此用$L=N$部分分的方法將全部$dp_{x,p}$預處理出來,而後用相似於預處理階乘逆元的方式預處理逆元,在更新乘法標記$a$的同時同步更新$a^{-1}$,就能夠作到嚴格的$O(n)$求解。

細節很是很是的多……寫題兩小時調試一成天

代碼

相關文章
相關標籤/搜索