線段樹 永久化標記優化

2021-08-30 02:43:56 字數 2157 閱讀 6767

誕生

正常的線段樹的改段求段都離不開lazy標記,lazy標記維護時要及時的更新,即人們熟知的pushdown函式。

那麼能不能避免這麼多次無意義的pushdown操作呢?他就是——標記永久化。

原理

舉個最簡單的例子,線段樹區間修改,求區間最大值。

這時的lazy存的是當前這一段待下傳的最大值,也就是說這個lazy最終會更新到這個線段的所有子線段。既然是他們共有的乙個最大值,那拼命地往下傳有什麼意義呢?還不如留在這個線段上,然後後面的子線段要用的時候再從這個線段上取就好了。可以保證,每個子線段的訪問前,必定會經過這個線段,所以就不用擔心標記遺漏傳遞的問題啦。

經過這樣的奇葩設計,我們的lazy就不必下傳了,但並不代表他不參與求最大值。因為在操作中,對於所有子線段返回的最大值,在經過當前線段時,會被max(lazt,ret)一下,即lazy也參與了最大值的計算。

畫一下重點,mx要保留,他表示的區間內的最大值;lazy要華麗變身,他表示的是當前區間以及所有子區間的最大值,所以所有有關子區間的問題他都要插一下手。mx處理的是區間完全覆蓋的問題,lazy是用來插手子區間的東東。根據這些,如果能理解mx一定比lazy大(優),就完全理解了標記永久化。

實現

接下來的有關**實現的可能要琢磨琢磨了。

更新:一到這個區間 mx等於max(mx,val)

if 區間恰好被覆蓋 then 更新lazy,結束這個區間的更新

往子區間繼續更新

詢問:if 區間恰好被覆蓋 then 返回mx,結束這個區間的更新

取到該區間的lazy

查詢子區間的最優答案

比較出lazy和子區間返回的答案中較優的,將其返回

(洛谷3437 [poi2006]tet-tetris 3d)給定乙個矩陣,初始每個位置上的元素都是0,每次選擇乙個子矩形,將這個子矩形內的值修改為這個子矩形內的最大值+h,求最終所有位置上的最大值。

題解

線段樹套線段樹+標記永久化

如果不用標記永久化的話,試想一下在外層線段樹的更新是不是要精確到區間中的每乙個線段樹,那和暴力就沒有區別了。

用永久化標記的話主要解決的是外層線段樹的問題,對於完全覆蓋的區間,打上永久化標記,即子節點返回的值要經永久化標記過審,所以就可以不用往後更新了。

**

#include#include#include#define lt x<<1,xl,mid

#define rt x<<1|1,mid+1,xr

#define rootx 1,1,n

#define rooty 1,1,m

using namespace std;

const int maxn=1100;//debug 陣列開小 

template inline void read(tp &x)

template inline void write(tp x)

int n,m,q;

struct segy

//debug 忘記return 

int mid=xl+xr>>1;

if(r<=mid) change(lt,l,r,val);

else if(mid>1,ans=tag[x];

if(r<=mid) return max( ans , query(lt,l,r) );

else if(mid>1;//debug mid=l+r>>1;

if(r<=mid) change(lt,l,r,yl,yr,val);//這些地方應當是繼續遞迴下去,而不是直接更改segy 

else if(mid>1,ans=tag[x].query(rooty,yl,yr);

if(r<=mid) return max( ans, query(lt,l,r,yl,yr) );

else if(midelse return max( ans , max( query(lt,l,mid,yl,yr) , query(rt,mid+1,r,yl,yr) ));

}}t;int main()

printf("%d\n",t.query(rootx,1,n,1,m));

return 0;

}

線段樹標記永久化

對於樹套樹,主席樹等使用到線段樹的比較複雜的資料結構,如果區間修改的話,打標記後pushdown或者pushup是很難做到的完全不行吧 所以這個時候,乙個神奇的東西誕生了。線段樹標記永久化,維護乙個標記,假設為cov,再維護乙個sum 假設修改區間 ql,qr 全部加上v 和平常一樣,到這個區間後c...

線段樹 標記永久化

一般線段樹做區間修改操作時,先是找到目標區間,然後修改該區間,並打下延遲標記,最後從目標區間自底向上,更新所有包含目標區間的區間的值 即pushup 當該區間子節點被訪問前,pushdown下推標記。這種維護區間的方式存在一點點弊端。例如用這種方式寫一棵可持久化線段樹,因為每次pushdown都相當...

線段樹標記永久化模板

題目如下 poj 3468 輸入整數n,q,然後輸入n個數的序列,再然後輸入q條詢問,詢問有兩種型別 q l r 代表列印出區間 l,r 的和 c l r v 代表區間 l,r 區間的數都加v 基本思路 這裡選擇線段樹,主要是為了練習線段樹標記永久化 下面介紹線段樹標記永久化 如下 include ...