建議把那個文件開啟放邊上,然後看這個。涉及到**的部分本文可能會省略。
not_only_success 線段樹
說到線段樹,首先要明確用陣列模擬樹的概念。以一顆二叉樹為例,若根為root 為1,為了方便陣列計算,那麼它的左右兒子可以用2, 3來表示,即 root << 1 和 root << 1 | 1
類似於:
在這個基礎上,如果把上面的節點換成區間,兩個子節點的區間合併剛好能組成父節點的區間,就可以做到類似於這樣的東西:
這就是線段樹的基本形態了。對於需要線段樹操作的乙個區間,每個數值都對應乙個父節點,他們的父節點記錄著操作要求中的資料。
舉個例子,比如說建一顆關於陣列a的線段樹,陣列a的值為: 5, 8 , 4, 13,並且這顆線段樹要完成的操作是求最大值
那麼構建出來的線段樹應該是這個樣子的:
總結一下:線段樹就是乙個區間管理的樹,其中乙個區間的子區間靠它的二分子節點來管理,一直到區間為一,也就是葉節點的位置。
然後是對not_only_success的線段樹的構建的講解,為了更方便更快的理解?
//首先有乙個定義,因為經常出現
//lson是左子樹,rson是右子樹,看過前面樹的陣列表示就能看懂的。
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
然後是建樹過程
build(int l, int r, int rt)
其中 當 l == r 的時候,代表已經到達最底下的葉子節點,也就是該是資料初始值的地方。 not_only_success的板不需要在節點上記錄左右區間,因為每個節點的區間其實可以靠 l 和 r 就完全確定了的。
更新和查詢可以直接看那個文件,沒有什麼特別的。
然後後面提一下寫了十多道題的時候遇到的一些情況:
1. 線段樹可以用來統計剩餘數量和位置。單點更新,區間查詢。
2. 線段樹的 加減乘,在使用lazy標記的時候,加減都是 += 更新完後置為0 乘的話,是*= 更新完後置為1
3. 線段樹的開根號操作,對於 int 的資料量,最多開6次,對於 long long 的資料,最多開8次。所以在更新的時候,lazy標記高於標值的就不用繼續更新了。
5. 哇,好像就沒有別的大問題了。
線段樹入門
線段樹 interval tree 是把區間逐次二分得到的一樹狀結構,它反映了包括歸併排序在內的很多分治演算法的問題求解方式。上圖是一棵典型的線段樹,它對區間 1,10 進行分割,直到單個點。這棵樹的特點 是 1.每一層都是區間 a,b 的乙個劃分,記 l b a 2.一共有log2l層 3.給定乙...
線段樹入門
學習下 線段樹的入門級 總結 線段樹是一種二叉搜尋樹,與區間樹相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。對於線段樹中的每乙個非葉子節點 a,b 它的左兒子表示的區間為 a,a b 2 右兒子表示的區間為 a b 2 1,b 因此線段樹是平衡二叉樹,最後的子節點數目為...
線段樹 入門
首先線段樹形象來說就是將陣列看成乙個線段,然後不斷的進行分割,儲存在樹中的不同節點上,有點類似於b 樹的定義吧 觀察上圖,首先將整個陣列的某種資訊 最大值或者最小值等 儲存在根節點,對應 1,8 然後對 1,8 線段進行平分,得到 1,4 和 5,8 兩個線段,掛在樹的第二層。這樣節點2儲存了陣列中...