唔突然不想寫那麼長的總結了
大概思想就是維護乙個點分樹,這樣保證了樹高是\(\log\)級別的,然後對於一些修改或者詢問,就可以支援諸如在點分樹上暴跳\(\text\)這樣的暴力做法了。
但是這並不是原來的樹,所以在點分樹上維護的資訊要以原樹為準。
具體題目具體分析,但大方向是在點 \(i\) 維護點分樹上點 \(i\) 的子樹的資訊,並且維護點 \(i\) 的子樹到點分樹上 \(i\) 的父親的資訊。不這樣做的話大概會把在原樹上點 \(i\) 和點 \(i\) 的父親(點分樹上)之間的聯通塊的答案多統計,這樣維護一下就可以減掉了。
下面是兩道題:
給定一棵樹,點有點權。要求支援修改點權,詢問距離點 \(x\) 小於等於 \(y\) 的點的點權和。\(n,m\leq 10^5\)。
這是最經典的維護上面說的兩個資訊,然後減一下保證答案不重複。
就是在每個點維護兩棵以距離為下標的線段樹,分別是點分樹上點 \(i\) 的子樹對於 \(i\) 的點權和,以及點 \(i\) 的子樹對於 \(fa[i]\) 的點權和。這樣做有什麼好處?
考慮詢問 \(dis=3\),我們先在點 \(x\) 求出所有到點 \(x\) 距離小於等於 \(3\) 的點權和,假設 \(dis(x,fa[x])=2\),那麼還要求出點 \(x\) 的子樹中到 \(fa[x]\) 距離小於等於 \(1\) 的點權和,然後把這部分答案減去。原因是會在跳到 \(fa[x]\) 時統計所有到 \(fa[x]\) 的距離小於等於 \(3-2=1\) 的點權和,這裡會重複統計,所以要提前減去。
先假設是一棵靜態的樹,怎麼求答案?
點分治。
對於所有 \(dis(i,u)+dis(j,u)\leq r[i]+r[j],(i,j)\) 是一對合法點對。移項發現兩項獨立,於是可以在節點 \(u\) 維護一棵平衡樹來統計\(\text\)。
那動起來怎麼辦呢?
動態點分治+定期重構點分樹。
每次還是加乙個節點,然後在點分樹上暴跳\(\text\)來統計答案。
但是如果是一條鏈怎麼辦?
所以需要像替罪羊樹那樣定期重構。
然後重構時有一些實現方面的問題,比如說每個點要開兩個\(\text\)記錄每個點在點分樹上的祖先和在原樹上到祖先的距離,還要開個\(\text\)記錄這個點在點分樹上的所有兒子。這樣做完全是為了方便重構點分樹。
具體重構就是,找到最靠上且需要重構的點,然後把它的子樹全部掃一遍,求出重心,然後遞迴去做。說起來挺簡單但是有一點細節?記得在平衡樹\(\text\)的時候\(+1\),把自己也放進存兒子的\(\text\)裡。就沒啥了。
**好的又填完乙個坑
點分治學習筆記
點分治主要用來處理樹上路徑問題,可以統計樹上點到點的所有路徑,複雜度o nlogn 基於樹上的結點進行分治,不斷將一棵樹拆成多顆子樹處理 選擇點時為了防止退化成鏈的情況,如果選點後左右子樹越大,遞迴層數越多,時間越慢,反之則越快,我們每次選擇子樹內的重心 void getroot int u,int...
點分治學習筆記
關於點分治,其實思想是非常好理解的,模擬在數列上或是在平面上的分治演算法 如歸併排序,平面最近點對等 我們可以從字面上理解該演算法 以乙個點為界限,將一棵樹分成若干個子樹,當劃分到一定規模,就對每個子樹分別進行求解 感性理解就好了 感受乙個演算法最直觀的辦法,就是來看一道模板題。給定一棵有 n 個點...
點分治學習筆記
point divide and rule 澱粉質就是在樹上,依靠不停的遞迴和分治,解決相同的子問題 先來看看模板題 tree 就是找樹上 k 的路徑有多少 我們可以分兩種情況討論 1.經過根節點 p 的路徑 2.不經過根節點 p 的路徑 第二種情況可以通過遞迴來處理,我們直接來討論第一種情況 設當...