線段樹 標記永久化

2021-08-26 02:56:50 字數 2362 閱讀 2278

一般線段樹做區間修改操作時,先是找到目標區間,然後修改該區間,並打下延遲標記,最後從目標區間自底向上,更新所有包含目標區間的區間的值(即pushup)。當該區間子節點被訪問前,pushdown下推標記。

這種維護區間的方式存在一點點弊端。例如用這種方式寫一棵可持久化線段樹,因為每次pushdown都相當於繼續之前延遲了的更新操作,所以得開新的節點,然後開著開著可能就爆記憶體了…..

一種更好的方法就是用標記永久化。 從字面意思就可以知道,永久化的標記是不會變的,這個不變是不會變小(一般的那種 pushdown的時候標記都清0了)。

實現過程:update[l,r]時,把所有包含[l,r]的區間更新(顯然修改[l,r]能影響到的就是這些區間),然後在[l,r]上打上標記;query[l,r]時,自頂向下找區間[l,r],統計從根到目標節點的路上標記的和,結果就是目標區間的值加上路徑上所有標記的影響。

優勢:不用pushdown,**短了,且可持久化的時候不用開新的節點;與下推標記的寫法相比略快一點

下面附上poj3468和hdu4348的**

poj3468

#include

#include

using

namespace

std;

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

const

int maxn = 100000+10;

typedef

long

long ll;

ll t[maxn<<2],lazy[maxn<<2];

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

int m = l+r >> 1;

build(lson);

build(rson);

t[rt] = t[rt<<1] + t[rt<<1|1];

}void update(int l,int r,int val,int l,int r,int rt)

int m = l + r >> 1;

if(r<=m)

update(l,r,val,lson);

else

if(l>m)

update(l,r,val,rson);

else update(l,m,val,lson), update(m+1,r,val,rson);

}ll query(int l,int r,int l,int r,int rt,int add)

int n,q;

int x,y;

ll z;

char str[10];

int main()

else

}return

0;}

hdu4348

#include

#include

#include

using

namespace

std;

const

int maxn = 1e5 + 5;

typedef

long

long ll;

int lazy[maxn*30],ls[maxn*30],rs[maxn*30],n,q;

ll t[maxn*30];

int tot,root[maxn],nowroot;

#define lson l,m,ls[now]

#define rson m+1,r,rs[now]

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

int m = l + r >> 1;

build(lson);

build(rson);

t[now] = t[ls[now]] + t[rs[now]];

//printf("t[%d] = %lld\n",now,t[now]);

}void update(int l,int r,int val,int l,int r,int &now,int lst)

int m = l + r >> 1;

if(r<=m)

update(l,r,val,lson,ls[lst]);

else

if(l>m)

update(l,r,val,rson,rs[lst]);

else

update(l,m,val,lson,ls[lst]), update(m+1,r,val,rson,rs[lst]);

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

void init()

int main()}}

}

線段樹標記永久化

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

線段樹 永久化標記優化

誕生 正常的線段樹的改段求段都離不開lazy標記,lazy標記維護時要及時的更新,即人們熟知的pushdown函式。那麼能不能避免這麼多次無意義的pushdown操作呢?他就是 標記永久化。原理 舉個最簡單的例子,線段樹區間修改,求區間最大值。這時的lazy存的是當前這一段待下傳的最大值,也就是說這...

線段樹標記永久化模板

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