這個線段樹運用了應用了add域優化,每個節點除了用value記錄當前節點對應區間元素的和之外,還要用add域記錄當前節點對應區間每個元素的增量。這樣,沒必要每次更新都要更新value更新到最底層每乙個點,只需要將增量記錄在某父節點的add域中即可,如果下次查詢或者更新操作的是該父節點對應區間的子區間,那麼就將add域更新下去,更新子節點的value值,完成更新或查詢。add域優化可以減少時間複雜度。
還有就是要注意查詢或者更新的區間遊客能橫跨左子樹和右子樹,在判斷的時候應該做處理。
#include #include#include
using
namespace
std;
#define maxn 4000000
struct
node
tree[maxn];
__int64 a[maxn],n;
void build( __int64 v, __int64 l,__int64 r ) //
對節點v進行建立,區間為l到r
__int64 mid=( l+r )/2
; build( v*2,l,mid ); //
左兒子 build( v*2+1,mid+1,r ); //
右兒子 tree[v].value=tree[v*2].value+tree[v*2+1].value; //
根據左右兒子更新當前節點
}void update(__int64 v,__int64 l,__int64 r,__int64 m) //
更新區間l-r加上m
if (tree[v].l==tree[v].r) return
;
__int64 mid=(tree[v].l+tree[v].r)/2
;
if (tree[v].add) //
下邊沒更新,傳遞增量
if (r<=mid)
if (l>mid)
update(v*2,l,mid,m); //
左右兒子都更新
update(v*2+1,mid+1
,r,m);
}__int64 query( __int64 v,__int64 l,__int64 r)
//查詢l-r上的v值
if (r<=mid)
return query(v*2,l,r); //
要查詢的區間全在左兒子
if (l>mid)
return query(v*2+1,l,r); //
全在右邊
return query(v*2,l,mid)+query(v*2+1,mid+1,r); //
橫跨左右邊
}int
main()
else
}return0;
}
暑假做的,又熟悉了一遍。。
POJ 3468 線段樹成段更新
題意就是給了一串行的數.然後不斷的問一段的值或者在一段上每個數加乙個數.輸出每次詢問的值.初看這題感覺就是最一般的線段樹成段更新的應用.但下手後發現很多細節.對於一向很粗心的我調了很久才給調出來.成段更新前一文已經提到過.這裡再通過這一題補充一些很值得注意的地方 1 前乙個題因為只有最後才要輸出一段...
POJ 3468 線段樹成段更新
很久以前的題目再做一遍複習一下。要點 1 約定在任何時候 add num 到達節點的時候就立即更新節點的 sum 值。2 每次更新節點回溯的時候記得維護節點的 sum 值。3 執行詢問操作的時候,遇到 lazy 標記為1 的時候往下 push down,同時記得第一點 4 遇到符合要求的詢問區間時,...
poj 3468線段樹 成段更新
題意和題目都很簡單,就是線段樹的成段更新,只要做一下延遲標記就好了。題意 查詢一段數的和,和更新一段數的值。一開始出了點錯誤,忘在更新時做延遲標記了。includelong long sum 100010 2 long long add 100010 2 void push up int rt vo...