樹鏈剖分並不是乙個複雜的演算法或者資料結構,只是能把一棵樹拆成鏈來處理而已,換一種說法,樹鏈剖分只是***資料結構/演算法在樹上的推廣,或者說,樹鏈剖分只是把樹hash到了幾段連續的區間上。(引用kuangbin大佬的)
個人對樹鏈剖分的理解:
因為線段樹只能處理像陣列一樣的線性的資料,對於樹這樣的結構,它顯得很無力,所以我們就用「樹鏈剖分」這種東西將樹拆成一小段一小段連續的鏈,這樣我們就得到了線性的資料,但這個線性的資料使用是有限制的,比如你跨段查詢或修改的時候就會出錯,那怎麼辦呢?我們知道此時任意兩個節點之間的路徑都被分成了若干段,既然不能跨段,那我們就一段一段處理,然後再合併一下。這時你可能會有疑問:(沒有的話,假設你有0.0)這種分段做法和暴力有多大區別?這就要看你是怎樣分段的了!我們要盡量使每段更長些,那麼我們就可以將任務盡可能多的交給線段樹處理,(具體處理看**),這樣其實複雜度差不多是log級別的!
大致操作過程:
技巧:處理以節點u為根的整個子樹:用線段樹處理[ wei[u] , wei[u] + siz[u] - 1]即可
查詢節點u和節點v的lca(最近公共祖先):將兩點不斷向上挪動並處理,直到兩點的top相同,dis小的點即是最近公共祖先
處理節點u到節點v的路徑上的點:將兩點不斷向上挪動並處理,直到兩點的top相同,最後用線段樹處理[wei[u] , wei[v] ]即可
處理節點u到節點v的路徑上的邊:將兩點不斷向上挪動並處理,直到兩點的top相同,最後用線段樹處理[wei[ son[u] ] , wei[v] ]即可(用每個點表示通向其父節點的邊)
入門:樹鏈剖分入門詳解 (講的很詳細,不懂得細心看哦)
訓練題:樹鏈剖分從入門到精通 (難度不一,適合從入門到深入哦)
下面貼個入門參照題(參照此**,a了入門題,就差不多算入門了)
good luck!(將**注釋全部開啟即是poj 2337的**)
#include#include#include#include#includeusing namespace std;
struct edge
edge[10005];
int tree[40005];
int son[10005],fa[10005],dis[10005],top[10005],siz[10005],wei[10005],len[10005],num;
vectorvec[10005];
void dfs1(int u,int f,int d)///樹鏈剖分套路
void gai(int l,int r,int node,int sign,int a)///線段樹修改
int query(int l,int r,int node,int ll,int rr)///線段樹查詢
/*void gai2(int l,int r,int node,int ll,int rr)
*/int yongth(int a,int b)///樹鏈剖分路徑分段處理
ans=max(ans,query(1,num,1,wei[tb],wei[b]));
b=fa[tb];
tb=top[b];
}if(a==b)return ans;
if(dis[a]>dis[b])swap(a,b);
ans=max(ans,query(1,num,1,wei[son[a]],wei[b]));
return ans;
}/*void yongth(int a,int b)
gai2(1,num,1,wei[tb],wei[b]);
b=fa[tb];
tb=top[b];
}if(a==b)return;
if(dis[a]>dis[b])swap(a,b);
gai2(1,num,1,wei[son[a]],wei[b]);
}*/void init(int n)///初始化
}int main()
dfs1(1,1,1);
num=0;
dfs2(1,1);
for(int i=1;i
樹鏈剖分入門
例題 poj 3237 bzoj 3083 bzoj 3531 bzoj 3589 bzoj 3626 將樹上問題通過dfs序的性質轉換為區間問題,從而對樹上修改時就可轉化為相應的區間修改。再通過引入重兒子,重鏈一系列概念將時間複雜度也變成了可以接受的層次 通過兩次dfs求出樹上一系列的資訊 voi...
樹鏈剖分入門
我學的學習資料 和 ppt 樹鏈剖分可以解決很多問題,輔助一些線段樹之類的資料結構可以解決一些樹上修改的問題。還可以求lca,不過複雜度比rmq實現的lca多乙個log。下面是樹鏈剖分實現的lca 1 const int maxn 5e4 10 2 struct data edge maxn 1 5...
樹鏈剖分入門
將樹分割成多條鏈,然後用線段樹等來維護這些鏈。樹鏈剖分的分割標準 連線乙個節點的子樹中的 重兒子 也就是結點最多的兒子,依次連下去。定義 重兒子 子樹節點的兒子 輕兒子 除了重兒子以外的兒子 重邊 父節點與重兒子組成的邊 輕邊 除重邊以外的邊 重鏈 重邊連線而成的鏈 輕鏈 輕邊連線而成的鏈 鏈頭 一...