點分樹學習筆記
關於點分樹的一些理解
定義與性質
點分樹,就是把點分治中的每一次的重心連起來,構成一棵樹。
由於重心的性質,點分治最多有 \(\lg n\) 層, 所以點分樹的樹高最多是 \(\lg n\)
維護
一般維護兩個值 \(s1\) 和 \(s2\) ,\(s1\) 表示這個點的子樹對於這個點的貢獻, \(s2\) 表示這個點的子樹對於這個點的父親的貢獻。\(s2\) 用於對 \(s1\) 進行容斥
每次修改時要在點分樹上不斷跳父親,修改點分樹上父親的資訊。
每次查詢時要在點分樹上不斷跳父親,詢問點分樹上父親的資訊,一般要用到容斥。用 \(s2\) 容斥 \(s1\)
具體看了題就理解了。
用途
一般用於靜態條件下點分治可解,但是強制線上或帶修的題。
注意事項
點分樹上的位置關係,距離關係,父子關係,祖孫關係,和原樹上不同。
luogu6329震波
標籤
點分治, 樹狀陣列
思路
先考慮不帶修的情況,那這就是道點分治裸題,但是這道題要求支援修改且強制線上。那麼點分治就不能用了。
所以我們要用點分樹。
對於每一個節點維護兩棵樹狀陣列 (\(vector\) 存) , \(s1\) 維護距離當前點距離為 \(k\) 的點的價值和, \(s2\) 維護距離當前點的點分樹上的父親距離為 \(k\) 的點的價值和。
對於修改操作,改成增加,然後在點分樹上不斷跳父親,修改 \(s1\) 和 \(s2\) 。
對於查詢操作,在點分樹上不斷跳父親,設詢問點和父親的距離為 \(d\)
維護兩棵樹狀陣列多麻煩啊,直接 \(s1[fa[i]].query(k - d) - s1[i].query(k - d - dis(i, fa[i]))\) 或者 \(s1[fa[i]].query(k - d) - s1[i].query(k - dis(i, x))\) 多方便,然而要注意 點分樹上的位置關係,距離關係,父子關係,祖孫關係,和原樹上不同。
所以這樣做是錯誤的。