線段樹 入門

2021-07-11 23:56:12 字數 1490 閱讀 3576

首先線段樹形象來說就是將陣列看成乙個線段,然後不斷的進行分割,儲存在樹中的不同節點上,有點類似於b_樹的定義吧

觀察上圖,首先將整個陣列的某種資訊(最大值或者最小值等)儲存在根節點,對應【1,8】

然後對【1,8】線段進行平分,得到【1,4】和【5,8】兩個線段,掛在樹的第二層。這樣節點2儲存了陣列中【1,4】的某種資訊(最大值或者最小值等),節點3儲存了【5,8】中的某種資訊。以此類推,直到線段長度為1,即葉子節點。

所以,要找尋陣列中某一區間的某些資訊,就直接從書中的某個節點或者多個節點的組合就可以得到了。

線段樹的操作主要有 建樹,查詢,更新。其中更新包括單點更新和區間更新。

#include #include using namespace std;

//線段樹 陣列實現 單點更新

#define max_node 200005

int in[max_node];

int segtree[4*max_node+10];

int build_tree(int root , int left , int right)

if (rightright || end=start && right<=end)//如果該節點記錄的區間是查詢區間的子集

return segtree[root];

//剩餘情況就是 該節點記錄的區間大於待查詢的區間 或者 該節點記錄的區間與待查詢區間有交集

// 節點記錄區間大於待查詢區間時,繼續遞迴查詢左右子樹

//節點記錄的區間與待查詢區間有交集 , 左右子樹總有乙個是記錄待查詢區間的子集

int mid = (left+right)>>1;

int part1 = query_tree(root*2 , left ,mid,start,end);//查詢左子樹

int part2 = query_tree(root*2+1 , mid+1 , right ,start , end);//查詢右子樹

//下面兩個判斷是針對節點記錄的區間與待查詢區間有交集但不是待查詢區間的子集。這樣肯定左右子樹中有乙個包含了待查詢區間的子集

if (part1 == -1)//如果左子樹不包含待查詢區間

return part2;

if (part2 == -1)//如果右子樹不包含待查詢區間

return part1 ;

//節點記錄區間大於待查詢區間時,此時左右子樹都包含了待查詢區間,所以取左右子樹返回的乙個最大值最為待求區間的最大值

return max(part1,part2);//

}int update_tree(int root , int left , int right , int updatenode , int value)

int mid = (left+right)>>1;

if (mid

線段樹入門

線段樹 interval tree 是把區間逐次二分得到的一樹狀結構,它反映了包括歸併排序在內的很多分治演算法的問題求解方式。上圖是一棵典型的線段樹,它對區間 1,10 進行分割,直到單個點。這棵樹的特點 是 1.每一層都是區間 a,b 的乙個劃分,記 l b a 2.一共有log2l層 3.給定乙...

線段樹入門

學習下 線段樹的入門級 總結 線段樹是一種二叉搜尋樹,與區間樹相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。對於線段樹中的每乙個非葉子節點 a,b 它的左兒子表示的區間為 a,a b 2 右兒子表示的區間為 a b 2 1,b 因此線段樹是平衡二叉樹,最後的子節點數目為...

線段樹入門

建議把那個文件開啟放邊上,然後看這個。涉及到 的部分本文可能會省略。not only success 線段樹 說到線段樹,首先要明確用陣列模擬樹的概念。以一顆二叉樹為例,若根為root 為1,為了方便陣列計算,那麼它的左右兒子可以用2,3來表示,即 root 1 和 root 1 1 類似於 在這個...