給定乙個區間\([1, n]\),希望你實現一種資料結構,支援以下操作:
1.修改\(i\)號節點的值。
2.詢問區間\([i, j]\)中所有節點的和。這不是樹狀陣列板子
3.修改區間\([i,j]\)中所有節點的值
4.詢問\(i\)號節點的值這不還是樹狀陣列板子
如果我要求乙個資料結構,同時滿足這四個要求。那樹狀陣列就不行了。
樹狀陣列其實也行
這時候就要引入乙個比樹狀陣列更高階的資料結構——線段樹
線段樹,顧名思義,就是一棵樹一顆乙個節點,儲存乙個區間的資訊的樹。如圖,就是乙個儲存\([1,10]\)的線段樹。
我們記\(l,r\)為節點\(k\)所儲存的區間的左右端點。顯然,當\(l == r\)時節點\(k\)為葉子結點。根節點儲存\([1,n]\)其餘節點儲存區間\([l,r]\)。對於任意乙個非葉子結點,他又兩個兒子為\(k << 1,k << 1 | 1\),分別儲存區間\([l,(l + r) >> 1]\)和\([(l + r) >> 1 + 1,r]\)。
首先,我們引入兩個函式:
\[ls(k)=k<<1
\]\[rs(k)=k<<1|1
\]我們用\(sum[k]\)表示\(k\)節點對應區間的區間和。易知\(sum[k] = sum[ls(k)] + sum[rs(k)]\)
這裡我們舉兩個例子
這樣,我們就可以把乙個區間長度為\(l\)的區間劃分成不超過\(2\log l\)個小區間,然後對這個小區間進行操作。因此每次操作的時間複雜度為\(o(\log n)\)對於\(n\)次操作時間複雜度為\(o(n \log n)\)。
預知後事如何,且聽下回分解
C 簡單介紹線段樹
如題,已知乙個數列,你需要進行下面兩種操作 將某區間每乙個數加上k。求出某區間每乙個數的和。第一行包含兩個整數n,m分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含3或4個整數,表示乙個操作,具體如下 1 x y k 將...
線段樹 02 構建線段樹
public inte ce merger 不能再縮小的基本問題是 對treeindex指向的節點的情況進行討論 public class segmenttree 在treeindex的位置建立表示區間 l.r 的線段樹 private void buildsegmenttree int treei...
線段樹 01 線段樹基礎
物理上 public class segmenttree public int getsize public e get int index 返回完全二叉樹的陣列表示中,乙個索引所表示的元素的左孩子節點的索引 private int leftchild int index 返回完全二叉樹的陣列表示中...