長鏈剖分學習筆記

2022-05-07 20:24:06 字數 1197 閱讀 4724

終於認真寫一次標題了

因為一些不明原因,之前對\(dsu\)

\(on\)

\(tree\)的理解沒有完全寫出來,在這裡會一起寫,因為兩者極為相似。

先來看一下\(dsu\)

\(on\)

\(tree\)和長鏈剖分的對比。

\(dsu\)

\(on\)

\(tree\)實際上就是重鏈剖分,可以處理很多與子樹有關且不帶修改的題目(離線),複雜度:\(\mathcal(nlogn)\)。

長鏈剖分實際上就是長鏈剖分,可以處理很多與深度有關且不帶修改的題目(離線),複雜度:\(\mathcal(n)\)。

可以看出,長鏈剖分比\(dsu\)

\(on\)

\(tree\)適用範圍更小,但更優秀。(具體原因後面會口胡)

考慮一下兩者的暴力,即為開乙個陣列維護資訊,每次跑一邊子樹維護資訊,再統計答案,複雜度顯然\(\mathcal(n^2)\)的。

因此,我們考慮保留,再將其他資訊加入,可以優化。

如果資訊和深度無關,考慮重鏈剖分,先跑輕兒子,並處理他的答案,注意這裡我們要清除資訊,再跑重兒子,保留資訊,處理答案,再暴力掃一遍輕兒子維護資訊即可。

而當資訊和深度有關時,顯然用長鏈剖分更優秀些,通過在乙個資訊陣列上的覆蓋,完成了上面的清除資訊(此處指標實現。

板子,直接上**,重點是這題卡空間,倍增過不了,\(vector\)也有點懸……

#includeusing namespace std;

inline int read()

while(x!=eof&&x>='0'&&x<='9')

return w*f;

}const int n=1000010;

int num_edge,n,q,top,ans[n];

int head[n],dep[n],max[n],son[n];

int stk[n],tmp[n<<2],*f[n],*now=tmp;

vector> que[n],anc[n];

struct edge edge[n];

inline void add(int from,int to)

inline void dfs_for_pre(int pos)

inline void long_chain_div(int pos)

int main()

學習筆記 長鏈剖分

處理和深度有關的一些事情 長鏈剖分的 和重鏈剖分一樣。只是重兒子條件不同罷了。之前和沒學一樣。補充 本質是優化dp,dp一維和深度有關 實現有一些類似dsu on tree 長鏈剖分還有乙個操作精髓是繼承長兒子的資訊 通常用指標分配記憶體,使得長兒子資訊更新位置恰好是x的位置偏移一位 共用部分陣列,...

長鏈剖分學習筆記

學這個之前應該要比較熟悉重鏈剖分,推薦一下這篇部落格。我們模擬重鏈剖分,定義每個點所有兒子中,子樹深度最大的點為它的重兒子,那麼整棵樹就被劃分成了一些不相交的重鏈,然後首先就有乙個性質那就是所有重鏈長度和是 o n 級別的,這個東西很顯然,還有乙個性質就是乙個點的k級祖先所在重鏈長度一定大於等於k,...

長鏈剖分學習筆記

長鏈剖分,也屬於樹鏈剖分的一種方式,但是其與經典的重鏈剖分又不太一樣。在重鏈剖分中,我們評判兒子重或輕的方式是比較其子樹節點數量。在長鏈剖分中,我們以子樹中最深的葉節點深度的大小來比較。其他步驟與重鏈剖分類似,都是兩遍dfs即可解決,都是o n 的複雜度。接下來,我們來看兩個長鏈剖分的經典問題.時間...