題目描述
給出一棵
給出
一個點
問有多少個點被控制。
分析
part 1 簡化的問題
不妨先看當
給出一棵樹,每次詢問距離點
x 的距離小於r 的點的個數。
考慮點剖,每一個重心上存點剖子樹中所有點,按照離重心距離爲關鍵字建桶。
那麼只需要在點剖樹上,從
但是注意可能會有重複計算。但是考慮點剖樹上某個點只有
時間複雜度
但是假如我們加入無用白點,那麼這裏可以
時間複雜度
邊剖也是類似的,不過相對來說更加好寫一點。
part 2 原問題的分解
擴展到多點 虛樹
當
虛樹的構建可以利用歐拉序,首先先將每兩個相鄰的關鍵點之間最近公共祖先都加入進去。然後維護一個棧,每加入一個點,就不斷退棧,直到棧頂是它的某個祖先,然後將棧頂與這個點連邊,最後將這個新點壓入棧。
首先先構建出這
爲了統一,假如某個點不被控制,不妨將
用spfa可以快速地計算出每個點的控制範圍。
然後問題的答案就等於虛樹上的每條邊的答案之和。
單條邊的處理方式
一條邊的答案正着算似乎不好處理,用所有的虛樹上點的控制範圍點數和,減去重複的部分,也可以得到原來的答案。
- 性質一:設
(x,y) 是虛樹上的一條邊,那麼當且僅當belongx≠belongy 時,纔會在這條邊上出現重複。
證明:顯然。 - 性質二:對於滿足性質一的邊,存在唯一的
z∈path[x,y] ,使得path[x,z] 上的點都屬x 管劾,path(z,y] 上的點都屬y 管劾。
證明:
不妨令depx<depy ,那麼
lx−dis(x,z)≤ly−dis(z,y)
lx−(depz−depx)≤ly−(depy−depz)
depx+depy+lx−ly≤2depz
⌈depx+depy+lx−ly2⌉≤depz
由上面這條式子,就可以知道z 唯一確定了一條邊之間兩個點的管劾範圍。
part 3 更深入的分析
通過這樣的劃分以後,我們計算答案的思路就變成下面兩步
假如某個點在新圖中存在勢力範圍,那麼統計它勢力範圍內的點數,將其求和。
對於每條兩個端點的統治勢力不同的點,計算它們重疊部分並減去之。
對於第一個問題,套用“簡化的問題”的思路,就可以簡單地解決了。
對於第二個問題,實際上就是要統計距離不在點
那麼對於第二個問題比較好的解決思路就是dfs序,因爲子樹都是dfs序中連續的一段,而不在子樹中必定是全段挖去中間的一小段。那麼我們只需要按dfs序構建主席樹,那麼就可以快速進行統計了。
那麼單次詢問的時間複雜度就是的時間複雜度
於是最終總的時間複雜度是