參考自
線段樹,類似區間樹,它在各個節點儲存一條線段(陣列中的一段子陣列),主要用於高效解決連續區間的動態查詢問題,由於二叉結構的特性,它基本能保持每個操作的複雜度為o(logn)。
線段樹的每個節點表示乙個區間,子節點則分別表示父節點的左右半區間,例如父親的區間是[a,b],那麼(c=(a+b)/2)左兒子的區間是[a,c],右兒子的區間是[c+1,b]。(父節點從0開始的情況)
由於線段樹的父節點區間是平均分割到左右子樹,因此線段樹是完全二叉樹,對於包含n個葉子節點的完全二叉樹,它一定有n-1個非葉節點,總共2n-1個節點,因此儲存線段是需要的空間複雜度是o(n)。
#include
#include
#include
using
namespace
std;
const
int infinite = int_max;
const
int maxnum = 1000;
struct segtreenode
segtree[maxnum]; //定義線段樹
/* 功能:構建線段樹
root:當前線段樹的根節點下標
arr: 用來構造線段樹的陣列 就是葉子節點的值val陣列
istart:陣列的起始位置
iend:陣列的結束位置
*/void build(int root,int arr,int istart,int iend)}/*
功能:當前節點的標誌域向孩子節點傳遞
root: 當前線段樹的根節點下標
*/void pushdown(int root)}/*
功能:線段樹的區間查詢
root:當前線段樹的根節點下標
[nstart, nend]: 當前節點所表示的區間
[qstart, qend]: 此次查詢的區間
*/int query(int root, int nstart, int nend, int qstart, int qend)
/*功能:更新線段樹中某個區間內葉子節點的值
root:當前線段樹的根節點下標
[nstart, nend]: 當前節點所表示的區間
[ustart, uend]: 待更新的區間
addval: 更新的值(原來的值加上addval)
*/void update(int root,int nstart,int nend,int ustart,int uend,int addval) //以增加值為例
//涉及到子樹了,延遲生效
pushdown(root);
//更新左右結點
int mid = (nstart + nend) / 2;
update(root*2+1, nstart, mid, ustart, uend, addval);
update(root*2+2, mid+1, nend, ustart, uend, addval);
//根據左右子樹的值回溯更新當前節點的值
segtree[root].val = min(segtree[root*2+1].val, segtree[root*2+2].val);
}
描述lily特別喜歡養花,但是由於她的花特別多,所以照料這些花就變得不太容易。她把她的花依次排成一行,每盆花都有乙個美觀值。如果lily把某盆花照料的好的話,這盆花的美觀值就會上公升,如果照料的不好的話,這盆花的美觀值就會下降。有時,lily想知道某段連續的花的美觀值之和是多少,但是,lily
的算術不是很好,你能快速地告訴她結果嗎?
輸入
第一行乙個整數t,表示有t組測試資料。
每組測試資料的第一行為乙個正整數n (n<=50000),表示lily有n盆花。
接下來有n個正整數,第i個正整數ai (1<=ai<=50) 表示第i盆花的初始美觀值。
接下來每行有一條命令,命令有4種形式:
(1)add i j, i和j為正整數,表示第i盆花被照料的好,美觀值增加j (j<=30)
(2)sub i j, i和j為正整數,表示第i盆花被照料的不好,美觀值減少j (j<=30)
(3)query i j, i和j為正整數,i<=j,表示詢問第i盆花到第j盆花的美觀值之和
(4)end,表示結束,這條命令在每組資料最後出現
每組資料的命令不超過40000條
輸出
對於第i組資料,首先輸出」case i:」和回車。
對於每個」query i j」命令,輸出第i盆花到第j盆花的美觀值之和。
樣例輸入
樣例輸出1
97 9 8 4 4 5 4 2 7
query 7 9
add 4 9
query 3 6
sub 9 6
sub 3 3
query 1 9
end
case 1:
1330
50
#include
#include
#include
#include
using
namespace
std;
const
int infinite = int_max;
const
int maxnum = 200010;
int arr[maxnum];
struct segtreenode
segtree[maxnum]; //定義線段樹
/* 功能:構建線段樹
root:當前線段樹的根節點下標
arr: 用來構造線段樹的陣列 就是葉子節點的值val陣列
istart:陣列的起始位置
iend:陣列的結束位置
*/void build(int root,int istart,int iend)}/*
功能:當前節點的標誌域向孩子節點傳遞
root: 當前線段樹的根節點下標
*/void pushdown(int root)}/*
功能:線段樹的區間查詢
root:當前線段樹的根節點下標
[nstart, nend]: 當前節點所表示的區間
[qstart, qend]: 此次查詢的區間
*/int query(int root, int nstart, int nend, int qstart, int qend)
/*功能:更新線段樹中某個區間內葉子節點的值
root:當前線段樹的根節點下標
[nstart, nend]: 當前節點所表示的區間
[ustart, uend]: 待更新的區間
addval: 更新的值(原來的值加上addval)
*/void update(int root,int nstart,int nend,int ustart,int uend,int addval) //以增加值為例
//涉及到子樹了,延遲生效
pushdown(root);
//更新左右結點
int mid = (nstart + nend) / 2;
update(root*2+1, nstart, mid, ustart, uend, addval);
update(root*2+2, mid+1, nend, ustart, uend, addval);
//根據左右子樹的值回溯更新當前節點的值
segtree[root].val = segtree[root*2+1].val + segtree[root*2+2].val;
} int main()
else
if(com[0] == 's')
else
if(com[0] == 'q')}}
return
0; }
線段樹基礎模板
c國的死對頭a國這段時間正在進行軍事演習,所以c國間諜頭子derek和他手下tidy又開始忙乎了。a國在海岸線沿直線布置了n個工兵營地,derek和tidy的任務就是要監視這些工兵營地的活動情況。由於採取了某種先進的監測手段,所以每個工兵營地的人數c國都掌握的一清二楚,每個工兵營地的人數都有可能發生...
簡單線段樹模板
入門第四天,前三天的沒時間補,回去再慢慢寫吧。今天學長講的是線段樹,講得很有老師的感覺.然後就是講的也都差不多聽懂了,只是有些細節在寫 的時候沒有注意到,一直錯。需要注意的點 1.在build的時候在left right時是node u a left 之前老是錯寫成node left a left ...
簡單線段樹(模板)
hdu 1754 模板,單點更新,區間查詢 1 include 2 include 3 include 4 include 5 include 6 include 7 include 8 include 9 include 10 include 11 include 12 define lson l...