線段樹區間覆蓋

2022-03-14 08:02:31 字數 2092 閱讀 3253

線段樹能支援什麼操作呢

對區間進行操作,我們肯定要使用懶標記

那麼懶標記的下放順序就是乙個問題

我們目前需要處理3個懶標記分別記為\(lazy,add,mul;\)

優先順序應該是\(lazy>mul>add\)

為什麼呢,首先是因為如果區間覆蓋,那麼前面更新的區間加,區間乘都會啞然失色,所以說區間覆蓋才是巨佬,那麼如果有區間覆蓋的

懶標記的話,我們當然是要先下放它,並把區間加,區間乘的懶標記設為沒有

按照順序的,仿照上面的依次考慮乘法標記,和加法標記

還有一種思想是需要我們知道,就是我們的懶標記是用到,我們就\(pushdown\),用不到,就讓它掛著就好,如果每次修改,我們都把懶標記

全部下放一邊,那和暴力沒有什麼差別了,懶標記也就是失去了它的意義,總歸,它的作用就是,當前修改的區間用的著的,我就下放,

用不著的,就在這個節點,隨著區間的更新懶標記就行

結構體

struct nodetr[n*4];
懶標記的下放,重中之重,打起精神了

void pushdown(int p)//因為懶標記的下放是對當前節點的左右兒子產生影響的,所以只用修改左右兒子的資訊,而當前點的資訊除了lazy外,都不用進行修改

tr[p<<1].mul*=tr[p].mul;//乘法標記

tr[p<<1|1].mul*=tr[p].mul;

tr[p<<1].sum*=tr[p].mul;//區間和直接乘上乘法標記

tr[p<<1|1].sum*=tr[p].mul;

tr[p<<1].add=tr[p<<1].add*tr[p].mul+tr[p].add;//加法標記

tr[p<<1|1].add=tr[p<<1|1].add*tr[p].mul+tr[p].add;

tr[p<<1].sum+=(tr[p<<1].r-tr[p<<1].l+1)*tr[p].add;

tr[p<<1|1].sum+=(tr[p<<1|1].r-tr[p<<1|1].l+1)*tr[p].add;

tr[p].mul=1;//乘法標記最開始也應該是為1的,表示沒有

tr[p].add=0;

}

剩下的需要進行修改的部分就是在修改\(update\)函式裡面了

void modify(int p,int l,int r,int add,int mul)

else

}pushdown(p);

int mid=(tr[p].l+tr[p].r)/2;

if(l<=mid)modify(p<<1,l,r,add,mul);

if(r>mid) modify(p<<1|1,l,r,add,mul);

pushup(p);

}

注意:由於我們的修改函式遞迴進行處理的,所以程式在到達遞迴邊界的時候,一定記得return,否則會進

入死迴圈

這裡有一道例題,我們來看一下\(cf343d \ water \ tree\)

這道題就是讓我們寫出乙個資料結構,使其能夠滿足下列操作

1.區間賦值

2.子樹賦值

3.單點查詢(區間會查詢,單點不會查詢,不丟人嗎)

子樹——樹剖,樹剖是肯定沒有跑的了,前面的還是極其套路的\(dfs1,dfs2,query,build\)

關鍵就在於修改的操作,我們需要修改的部分也就是區間覆蓋的懶標記出現的位置

乙個在\(pushdown\)裡面

inline void pushdown(int p)

}

乙個在\(update\)函式裡面

inline void update(int p,int l,int r,int k)

pushdown(p);

int mid=(tr[p].l+tr[p].r)/2;

if(l<=mid) update(p<<1,l,r,k);

if(r>mid) update(p<<1|1,l,r,k);

pushup(p);

}

完結撒花

線段樹線段覆蓋(離散化 區間覆蓋)

n n 10000 個人依次貼海報,給出每張海報所貼的範圍li,ri 1 li ri 10000000 求出最後還能看見多少張海報。input 第一行 樣例個數t 第二行 貼海報的人n 第三行 每個人貼海報的範圍 接下來n行 每個人貼海報的範圍 output 對於每乙個輸入,輸出最後可以看到的海報張...

線段樹(區間樹)

目錄 為什麼要使用線段樹 什麼是線段樹 線段樹融合介面 線段樹實現 線段樹例題 融合介面 author administrator param public inte ce merger package com.suanfa.segmenttree 線段樹 區間樹 author administra...

線段樹 區間樹

每乙個節點儲存的是乙個區間中相應統計值 在treeindex的位置建立表示區間 l.r 的線段樹 private void buildsegmenttree int treeindex,int l,int r int lefttreeindex leftchild treeindex int rig...