高階 樹鏈剖分

2021-09-25 05:57:41 字數 1629 閱讀 4027

之前寫過乙個基本的樹鏈剖分,但是我今天要講的高階版樹鏈剖分要能支援以下操作:

其實還是板子題

其他的前置知識:樹狀陣列支援區間修改區間查詢(單純圖個方便),不會的話可以看這裡 。

說說高階其實也沒什麼東西。。。

相較於我原來寫的 blog 只多了修改詢問子樹和換根的操作,但不得不說換根操作是真的妙,值得講一講。

先將換根吧。假設原來的根是 rtrt

rt,新的根是 new

rt

newrt

newr

t 。那麼換根**只有一行 rt=

newr

trt = newrt

rt=new

rt。這下有人要噴了,這不什麼都沒幹嘛。說得對,確實什麼都沒乾,但是也很好理解,樹鏈剖分沒有 lct 那麼靈活,每次換根重構整棵樹的話時間上實在支撐不起。

但是由於這個原因,修改詢問子樹就比原來要複雜一些了,修改和詢問大致都可以分為三種情況,這裡以修改為例:

class binaryindexedtree 

inline void update(int x, long long v)

inline long long query(int x)

public:

inline void update(int l, int r, long long v)

inline long long query(int l, int r)

} bit;

class treechain

}inline void dfstop(int u, int tp)

ted[u] = dfsclock;

}inline int reach(int x, int y)

return x == y ? ans : son[y];

}public:

inline void init(int rt)

inline void changeroot(int rt)

inline void updateinit(int x, int v)

inline void updateroute(int x, int y, int z)

if (depth[x] > depth[y])

std::swap(x, y);

bit.update(tid[x], tid[y], z);

}inline long long queryroute(int x, int y)

if (depth[x] > depth[y])

std::swap(x, y);

return ans + bit.query(tid[x], tid[y]);

}inline void updatesubtree(int x, int z) else

bit.update(tid[x], ted[x], z);

}inline long long querysubtree(int x) else

return bit.query(tid[x], ted[x]);

}};

必須壓壓行了,否則這個碼量堪稱恐怖,但其實仔細觀察其中的一半都是可以 ctrl + c 和 ctrl + v 解決的。

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...

演算法入門 樹鏈剖分 輕重鏈剖分

目錄 3.0 求 lca 4.0 利用資料結構維護資訊 5.0 例題 參考資料 資料結構入門 線段樹 發表於 2019 11 28 20 39 dfkuaid 摘要 線段樹的基本 建樹 區間查詢 單點修改 及高階操作 區間修改 單點查詢 區間修改 區間查詢 標記下傳 標記永久化 閱讀全文 樹鏈剖分用...

樹鏈剖分 樹剖換根

這是一道模板題。給定一棵 n 個節點的樹,初始時該樹的根為 1 號節點,每個節點有乙個給定的權值。下面依次進行 m 個操作,操作分為如下五種型別 換根 將乙個指定的節點設定為樹的新根。修改路徑權值 給定兩個節點,將這兩個節點間路徑上的所有節點權值 含這兩個節點 增加乙個給定的值。修改子樹權值 給定乙...