學習筆記 第九課 點分治和點分樹 動態點分治

2022-04-29 05:33:14 字數 1488 閱讀 9773

點分治一般是用來解決樹上路徑統計的問題, 而動態點分治(也稱點分樹),是用資料結構樹上路徑資訊。

首先顯然的\(\theta (n^2 \log n)\)的列舉演算法

for (int i = 1; i <= n; i ++ ) 

}

比較難優化,我們可以換一種考慮方式。

以\(p\)為樹根, 則對\(p\)而言, 樹上的路徑可以分為兩種

1.經過\(p\)的路徑

2.不經過\(p\)的路徑(包含於\(p\)的某個子樹中)

第\(2\)種情況我們可以遞迴(以子樹的根再進行計算)

void solve (int u) 

}

這樣最劣時間複雜度仍為\(\theta(n^2 \log n)\) 鏈既可以卡掉

如果遞迴到\(t\)層,那麼時間複雜度為\(\theta (tn\log n)\)

如何讓\(t\)盡可能的小,我們可以每次選擇樹的重心作為根節點\(p\),容易證明點分治至多遞迴\(\log n\)層,時間複雜度也優化到了\(\theta (n \log ^ 2n)\)

點分治的過程為\(4\)步

1.選當前子樹的重心\(p\)作為根節點

2.從\(p\)出發進行一次\(dfs\),求出對應資訊

3.執行\(solve(p)\)

4.標記\(p\),遞迴執行\(p\)的每棵子樹

** code

逆元預處理即可

用樹狀陣列維護資訊(細節:樹狀陣列不能出現\(0\),所以集體向右偏轉\(1\))

首先我們回憶一下點分治的過程,對於當前重心,他管轄的是經過他的路徑,那麼我們考慮修改乙個點,那麼有至多有\(\log n\)個重心路徑受影響,我們可以用資料結構來維護相關資訊,即可在\(\log ^2 n\)的時間解決。

對於每乙個點,我們可以開一顆權值樹狀陣列\(/\)權值線段樹來維護,由於空間開不下所以常常要用動態開點線段樹。維護經過當前點距離為\(s\)的點權之和。

我們可以在處理重心的時候檢出乙個點分樹,及兩兩重心相連(不用建出來,只要建立上一層的重心即可)。

inline void insert (int rt, int id, int u, int f) 

}inline void solve (int u)

}

我們查詢距離\(u\)點距離\(\leq k\)的路徑

ans += query (rt[u], 0, n, k);

for (int i = u; fa[i]; i = fa[i])

但這樣我們發現有問題,因為有些路徑重複算了,我們要減去子樹的影響。

ans += query (rt[u][0], 0, n, k);

for (int i = u; fa[i]; i = fa[i])

return ans;

同理修改也可以得出。

** code

Python全棧 第九課 學習筆記

函式的結構與呼叫 函式什麼時候執行?函式的返回值 s1 fsjkdafshdjfsdhafjksda l1 1,2,3,4,5,6 def my len s count 0 for i in s count 1 print count my len s1 my len l1 return 在函式中遇...

python基礎第九課筆記和作業

用函式實現乙個判斷使用者輸入的年份是否是閏年的程式 def runnian years if years 4 0and years 100 0 or years 400 0 print years,是閏年 else print years,不是閏年 runnian 2021 猴子吃桃問題 遞迴 猴子...

Python學習第九課 匿名函式

匿名函式 func lambda x x 1 x表示引數 x 1表示處理邏輯 print func 10 輸出結果為11 例 如何將name hanhan 改為 hanhan shuai的形式 普通函式寫法 name hanhan def change name x return name shua...