點分治,動態點分治,等等等各種分治。
因為我的智商經常欠費,導致我對於分治這個方面一竅不通。
但是動態點分治這個東西我又不是沒有學過,只是過了這麼久我什麼都不會了。
所以還是重新理解一下吧。。。
首先,動態點分治需要構建出點分樹,這個很好處理。
找重心是o(
n)o (n
),每次重心分出來的每一棵子樹的大小都不超過o(
n/2)
o (n
/2
)所以總的複雜度是o(
nlog
n)o (n
logn
)的。
點分樹中的父子關係和原樹中差距較大,但是並不影響我們對於資訊的維護。
點分樹的樹高是lo
g log
級別的,因此在點分樹上暴力向上維護的複雜度是正確的。
因為點分樹上的父子關係和原樹的父子關係差距較大,
我們來考慮如何維護點分樹上的資訊。
按照題目來舉例子,比如【bzoj3730】震波
我們需要維護的東西是對於當前點距離不超過
x x
的點。
我們看看在原樹中這個東西怎麼找:
我們確定乙個根,轉化為有根樹。
對於每個點維護距離它不超過
x' role="presentation">x
x的所有子樹中的點,統計一下。
然後跳到父親,統計一下距離父親距離不超過x−
1 x−1
的所有子樹中的點,
但是發現當前點中有一部分被重複算了,所以再減去距離當前點子樹中距離不超過x−
1 x−1
的點。
然後繼續跳到父親的父親……
因為點分樹上的所有點的,都是原樹中一棵子樹的重心,
我們可以認為點分樹上所有點的子樹就是這個點在原樹上的子樹,只不過我們看的根不太一樣而已。
既然這樣,我們就可以向上面那樣求解:
維護距離當前點不超過
x x
的所有子樹中的點。
跳到父親,假設父親和當前點的距離為
d' role="presentation">d
d,找一下距離父親不超過
d d
的點。
然後減去距離當前點距離不超過
d' role="presentation">d
d的所有點。
然後跳到父親的父親……
這樣是對的原因也很簡單:當前點一定是點分樹上父親的子樹中的乙個點。
那麼我們在維護這個點的同時,只需要像上面所寫的那樣,再維護一下當前點對於父親的貢獻就好了。
點分治 動態點分治
實在拖得太久了。先扔掉資料 分治的核心是盡量把乙個整體分成接近的兩個部分,這樣遞迴處理可以讓複雜度從n 變成nlogn。兩個問題,如何區分和如何算答案。對於第乙個問題,重心,然後就是找重心的方法,兩個dfs,對於第二個問題,對於每個重心算當前塊中每個點到重心的答案,然後由重心分開的塊要把多餘的資訊去...
點分治與動態點分治
點分治一般是用於解決樹上路徑問題。樹的重心 把重心這個點割掉後,使所形成的最大的聯通塊大小最小的點。可以證明重心子樹的大小最大不會超過 n over 2 重心可以通過 dfs 一遍求出。maxsiz x 表示割掉點x後所形成的的最大的聯通塊的大小 void dfs int x,int fa max ...
點分治 複習筆記
之前diaoye的一道題是要用點分治寫.但是我省選前臨時學的點分治,當時又只打了幾個板子,中間又沒有寫過有關的題,於是現在就似乎不太會了,剛好昨天又講了,今天就複習一下 引用講課pp t ppt 裡的一段話 點分治,是處理樹上路徑 連通塊的一種常見演算法。這一類問題有時可以通過lca來處理,但是有的...