線段樹標記永久化

2021-08-14 09:17:49 字數 941 閱讀 4057

對於樹套樹,主席樹等使用到線段樹的比較複雜的資料結構,如果區間修改的話,打標記後pushdown或者pushup是很難做到的完全不行吧

所以這個時候,乙個神奇的東西誕生了。。。

線段樹標記永久化,維護乙個標記,假設為cov,再維護乙個sum

假設修改區間[ql, qr]全部加上v:

和平常一樣,到這個區間後cov[x] += v

但是我們又不想pushup,怎麼辦?

很好做,更新的時候每次sum[x] += v * (qr - ql + 1) (注意這裡的qr,ql是完全被包含於線段樹[l, r]區間內的)

這個很好理解

void modify(int x, int l, int r, int ql, int qr, int v)

intmid = (l + r) >> 1;

if(qr <= mid) modify(x << 1, l, mid, ql, qr);

else

if(ql > mid) modify(x << 1 | 1, mid + 1, r, ql, qr);

else modify(x << 1, l, mid, ql, mid), modify(x << 1 | 1, mid + 1, r, mid + 1, qr);

}

那麼詢問怎麼辦

假設我們現在乙個區間都打上了標記,表示為這個區間的子區間都需要累加區間修改

換句話說,該區間需要累加某個區間的標記,當且僅當這個區間完全包含該區間,這不就是線段樹詢問時從上往下累加標記就行了嗎?

最後,累加的標記ad * (r - l + 1) + sum[x]就是詢問的答案

int query(int x, int ad, int l, int r, int ql, int qr)
特別鳴謝 orz zsy教會我標記永久化

線段樹 標記永久化

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

線段樹 永久化標記優化

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

線段樹標記永久化模板

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