與樹狀陣列類似,用來處理陣列的區間查詢和元素更新操作。
與樹狀陣列類似,用來處理陣列的區間查詢和元素更新操作。
與樹狀陣列類似,用來處理陣列的區間查詢和元素更新操作。
重要的事情說三遍!!!!
相較於樹狀陣列,線段樹還可以進行區間最大值,最小值的查詢,更加的靈活。
複雜度線段樹在邏輯上使用完全二叉樹的資料儲存結構來實現樹結點的儲存,這個儲存結構可以參考堆的儲存邏輯。更新(update):o(logn)
查詢(query):o(logn)
特點:線段樹這棵二叉樹每乙個結點對應乙個區間的資訊(資訊的意思是指:區間的最大值、最小值、和等等)
性質
不妨我們以array=為原陣列,構建乙個求區間和的線段樹,模樣如下
線段樹的構建基本類似於其他樹的構建,也是用遞迴的方法進行構建。
對於線段樹的儲存,由於線段樹在儲存邏輯上是 類似於完全二叉樹 的一種形式,所以我們選擇使用陣列進行儲存,並且我們陣列的下標從1開始!
使用線段樹求區間最大最小值和區間和的**有所不同
在這,我們以求區間最小值為目標建立線段樹陣列
我們以求區間最小值為目標建立線段樹陣列
我們以求區間最小值為目標建立線段樹陣列
結構體
struct segtreenode
tree[maxnum]
;// 定義線段樹
先給出線段樹的create函式
// node是當前結點
// begin是當前處理區間的開始
// end是當前處理區間的結尾
// 處理在本例中的意思時取區間最小值
// tree是線段樹結點儲存的陣列
// array是給出的乙個普通陣列
void
create
(int node,
int begin,
int end)
else
}main呼叫:create(1
,0, n-1)
;// tree[1]記錄的是array陣列區間為[0,n-1]的最小值
查詢query函式
long
long
query
(int root,
int nowleft,
int nowright,
int queryleft,
int queryright)
然後是線段樹的update函式(區間修改)
// 將延遲標記向子結點進行傳遞
void
pushdown
(int root)
}// update函式
// nowleft是現在的判斷區間的起始位置
// nowright是現在的判斷區間的結束位置
// updateleft是更新區間的起始位置
// updateright是更新區間的結束位置
void
update
(int root,
int nowleft,
int nowright,
int updateleft,
int updateright,
int addval)
pushdown
(root)
;//延遲標記向下傳遞
//更新左右孩子節點
int nowmid =
(nowleft + nowright)/2
;update
(root*
2, nowleft, nowmid, updateleft, updateright, addval)
;update
(root*2+
1, nowmid +
1, nowright, updateleft, updateright, addval)
;//根據左右子樹的值回溯更新當前節點的值
tree[root]
.value =
min(tree[root *2+
1].value, tree[root *2+
2].value)
;}
洛谷:p3372
如題,已知乙個數列,你需要進行下面兩種操作:
將某區間每乙個數加上 kk。
求出某區間每乙個數的和。
第一行包含兩個整數 n, mn,m,分別表示該數列數字的個數和操作的總個數。
第二行包含 nn 個用空格分隔的整數,其中第 ii 個數字表示數列第 ii 項的初始值。
接下來 mm 行每行包含 33 或 44 個整數,表示乙個操作,具體如下:
1 x y k
:將區間 [x, y][x,y] 內每個數加上 kk。
2 x y
:輸出區間 [x, y][x,y] 內每個數的和。
輸入 #1
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
輸出 #1
11
820
題目大意:給乙個大小為n的陣列,再給m條指令,若指令為1,將[x,y]內的數字全部加上k;若指令為2,求出區間[x,y]的區間和
分析:這是一道線段樹模板題,根據題目的意思,我們需要去維護乙個求區間和的線段樹,然後根據不同的指示進行操作
**:
#include
#include
#include
using
namespace std;
// 線段樹結構體
struct segtree
;//array陣列是題目給定陣列
//tree是進行維護的線段樹陣列
vector<
long
long
> array;
vector tree;
int n, m;
/* * 線段樹求區間和模板
* 與求最大最小值的模板略有不同
*///建立線段樹
void
create
(int node,
int begin,
int end)
else
}//相較於求最值時的pushdown函式,增加了左右區間:l和r。原因在函式內注釋中
void
pushdown
(int root,
int l,
int r)
}//更新線段樹
void
update
(int root,
int nowleft,
int nowright,
int updateleft,
int updateright,
int addval)
pushdown
(root,nowleft,nowright)
;int nowmid =
(nowleft + nowright)/2
;update
(root*
2, nowleft, nowmid, updateleft, updateright, addval)
;update
(root*2+
1, nowmid +
1, nowright, updateleft, updateright, addval)
;//求區間和。相比於求最值線段樹,結點更新函式需要變化
tree[root]
.value = tree[root*2]
.value + tree[root*2+
1].value;
}long
long
query
(int root,
int nowleft,
int nowright,
int queryleft,
int queryright)
intmain()
else
}return0;
}
普通線段樹維護區間最大最小值(板子)
線段樹維護區間最大 小值就是按照原來給出的資料的順序建造一顆二叉樹,然後每乙個節點維護 這個節點的子節點且包含這個節點的值中的最大 小值 include include include include using namespace std define ll long long const int...
線段樹 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 返回完全二叉樹的陣列表示中...