點分治學習語文學習
大致功能
計算靜態樹上的符合條件的路徑的數量,長度等
eg:
- 統計長度小於k的路徑數量
- 經過特殊點不超過𝑘個的最長路徑長度
基本原理
正難則反
對某棵子樹,指定一個根root,將這棵子樹作爲分治單位,統計其路徑
路徑分爲兩種:
1.經過root(起點和終點不在一棵root的兒子的子樹中)
2.不經過root(在一棵中)
首先統計這顆子樹上所有過root的可重路徑
設root的兒子爲v,假設樹已分層,兒子的層數較大,
顯然,這些路徑包括
1. 起點終點在同一棵v的向下子樹的路徑
2. 起點和終點不在同一棵v的向下子樹的路徑
要把第一種路徑數量減掉!!
那麼,對於root的每個兒子v,第一種路徑的數量就等於 v的向下子樹中過v的所有可重路徑 的和!
妙啊
那麼有個問題,如果直接把兒子當根的話,樹每次分成的子樹大小相差太大,有可能每次只分出非常小的幾棵和非常大的一棵,所以分一棵的時候,複雜度可能會從log變成n,所以總的複雜度就呵呵了
所以要讓這個根的子樹的大小儘可能平均,所以可以選擇重心作爲某棵子樹的根,相當於把這棵子樹砍下來,把重心提起來,對他在進行分治!
O(n) 求重心的方法:
dfs遍歷,(假設給樹分層)計算每個點的向下子樹的大小,若某個點的兒子的向下子樹和父親的向上子樹的大小的最大值更小,則將根更新爲它
那麼,點分治間接統計的總的步驟就是這樣:
1.求出根𝑟𝑜𝑜𝑡
2.得到相關信息,統計第2類路徑並累加入答案中
3.刪除節點𝑟𝑜𝑜𝑡,對於𝑟𝑜𝑜𝑡的每一棵子樹遞歸的執行分治算法
應用
主要是思考如何設計統計的函數
一. 統計長度小於k的路徑數
間接法:尺取法+單調性:可以On求數組中滿足某個約束的數對的數量
二.經過特殊點不超過𝑘個的最長路徑長度
直接法 樹上直接統計:遍歷兒子,使用一個數據結構,維護前面的兒子的向下子樹情況,用於計算有關於這個兒子的向下子樹的那部分可能的答案
對前i個兒子的向下子樹維護一個樹狀數組,記錄不超過k個特殊點時從root出發的路徑長度的最大值,也就是前綴最大值,計算從root到這個兒子的向下子樹中每個點的特殊點的數量m和距離,與前面的兒子經過特殊點不超過k-m個的最長路徑相加更新總答案,再遍歷一遍更新樹狀數組。等所有兒子遍歷完之後遍歷以遍兒子的子樹,清除樹狀數組