線段樹成段更新需要用到延遲標記(或者說懶惰標記),簡單來說就是每次更新的時候不要更新到底,用延遲標記使得更新延遲到下次需要更新or詢問到的時候。延遲標記的意思是:這個區間的左右兒子都需要被更新,但是當前區間已經更新了。其主要使用了lazy思想。
lazy思想:lazy-tag思想,記錄每乙個線段樹節點的變化值,當這部分線段的一致性被破壞我們就將這個變化值傳遞給子區間,大大增加了線段樹的效率。
在此通俗的解釋lazy(t偷懶)的意思,比如現在需要對[a,b]區間值進行加c操作,那麼就從根節點[1,n]開始呼叫update函式進行操作,如果剛好執行到乙個子節點,它的節點標記為rt,這時tree[rt].l == a && tree[rt].r == b 這時我們可以一步更新此時rt節點的sum[rt]的值,sum[rt] += c * (tree[rt].r - tree[rt].l + 1),注意關鍵的時刻來了,如果此時按照常規的線段樹的update操作,這時候還應該更新rt子節點的sum值,而lazy思想恰恰是暫時不更新rt子節點的sum值,到此就return,直到下次需要用到rt子節點的值的時候才去更新,這樣避免許多可能無用的操作,從而節省時間 。
#define _crt_secure_no_deprecate#include#include
const
int maxn = 100000+10
;typedef
long
long
ll;using
namespace
std;
struct
tnode;
tnode tree[
4*maxn];
intn;
void build(int v, int b, inte)}
void update(int v, int l, int
r, ll value)
tree[v].sum += value*(r - l + 1); //
將增加的值更新進去
int mid = (tree[v].b + tree[v].e) >> 1
;
if (r <=mid)
update(
2 * v + 1
, l, r, value);
else
if (l >mid)
update(
2 * v + 2
, l, r, value);
else
}ll qurrey(
int v, int l, int
r)
int mid = (tree[v].b + tree[v].e) >> 1
;
if (r <=mid)
return qurrey(2 * v + 1
, l, r);
else
if (l >mid)
return qurrey(2 * v + 2
, l, r);
else
return qurrey(2 * v + 1, l, mid) + qurrey(2 * v + 2, mid + 1
, r);
}int
main()
while (q--)
}return0;
}
POJ 3468 線段樹成段更新
題意就是給了一串行的數.然後不斷的問一段的值或者在一段上每個數加乙個數.輸出每次詢問的值.初看這題感覺就是最一般的線段樹成段更新的應用.但下手後發現很多細節.對於一向很粗心的我調了很久才給調出來.成段更新前一文已經提到過.這裡再通過這一題補充一些很值得注意的地方 1 前乙個題因為只有最後才要輸出一段...
poj 3467 線段樹成段更新
題意 略 分析 可設一另設兩個域sum 和d分別表示該區間的當前和與該區間的每個元素的增量,之後維護線段樹即可!再次感慨 能力 include using namespace std int64 sum1 int a 100005 struct node tree 1000000 void crea...
POJ 3468 線段樹成段更新
很久以前的題目再做一遍複習一下。要點 1 約定在任何時候 add num 到達節點的時候就立即更新節點的 sum 值。2 每次更新節點回溯的時候記得維護節點的 sum 值。3 執行詢問操作的時候,遇到 lazy 標記為1 的時候往下 push down,同時記得第一點 4 遇到符合要求的詢問區間時,...