線段樹 區間修改(Lazy Tag)

2021-08-07 08:52:30 字數 1570 閱讀 5059

poj3468a ****** problem with integers

傳送門

注意ans可能超出int

懶惰標記

:之所以稱為懶惰標記,是因為我們在區間修改時,只修該結點的值,並在節點新增加乙個標記,讓子節點暫時處於不更新的狀態,等我們用到的時候再更新,這樣當我們在查詢的時候,如果我們到了乙個節點p,並且決定考慮其子節點,那麼我們就要看節點p是否被標記,如果有,就要按照標記一次性修改其子節點的資訊,並且給子節點都標上相同的標記,同時消掉節點p的標記。

區間更新舉例說明:當我們要對區間[0,2]的葉子節點增加2,利用區間查詢的方法從根節點開始找到了非葉子節點[0-2],把它的值設定為1+2 = 3,並且把它的延遲標記設定為2,更新完畢;當我們要查詢區間[0,1]內的最小值時,查詢到區間[0,2]時,發現它的標記不為0,並且還要向下搜尋,因此要把標記向下傳遞,把節點[0-1]的值設定為2+2 = 4,標記設定為2,節點[2-2]的值設定為1+2 = 3,標記設定為2(其實葉子節點的標誌是不起作用的,這裡是為了操作的一致性),然後返回查詢結果:[0-1]節點的值4;當我們再次更新區間[0,1](增加3)時,查詢到節點[0-1],發現它的標記值為2,因此把它的標記值設定為2+3 = 5,節點的值設定為4+3 = 7;

其實當區間更新的區間左右值相等時([i,i]),就相當於單節點更新,單節點更新只是區間更新的特例。

#include #include #define maxn 100010

#define lson l,mid,now<<1

#define rson mid+1,r,now<<1|1

#define ll long long int

ll f[maxn<<2],a[maxn],lazy[maxn<<2];

void build(int l,int r,int now)

int mid=(l+r)>>1;

build(lson);

build(rson);

f[now]=f[now<<1]+f[now<<1|1];

return;

}void pushdown(int ln,int rn,int now)

}//區間修改a[l...r]+x

void update(int l,int r,int x,int l,int r,int now)

int mid=(l+r)>>1;

pushdown(mid-l+1,r-mid,now);//傳遞使命

if(l<=mid) update(l,r,x,lson);

if(r>mid) update(l,r,x,rson);

f[now]=f[now<<1]+f[now<<1|1];

}//區間查詢

ll query(int l,int r,int l,int r,int now)

int main()

else if(ch=='c')

getchar();

} }return 0;

}

線段樹 區間修改

我們對於線段樹的區間修改你可以用乙個最傻的辦法迴圈進行單點修改 時間複雜度太高十分麻瓜 所以,我們要用乙個聰明的做法延遲標記 lazy 我們在執行修改指令時,同樣可以在 l pl pr r 的情況下立即返回,只不過在回溯之前向節點p增加乙個標記,標識 該節點曾經被修改過,但其子節點尚未被更新 如果在...

hdu Just a Hook(線段樹區間修改)

線段樹模板題,練的是懶惰標記。懶惰標記,就是更新一段區間的時候,如果小區間被包含在了所需要更新的區間裡面,那麼直接對代表這個區間的陣列元素賦值,之後做乙個標記 表示這個區間的子區間都需要更新 但是不繼續遞迴 這樣可以節省很多的時候 11657115 2014 09 15 14 17 26 accep...

線段樹區間修改模板

本來打算把大白書第三章一口氣攻下來的,但是這個線段樹也是卡了好久。不敢過題太快,怕自己走馬觀花到頭來結果什麼都不會。可也不能再拖了,在做題中也許有更多的體會。模板一 1 l r v 表示區間 l,r 所有元素都加上v 2 l r 表示查詢區間 l,r 的sum,min,max sumv o 的定義為...