線段樹002 區間修改

2021-08-25 11:45:07 字數 1235 閱讀 3893

接下來講解一下區間修改:

比如在下面這個圖中我要將1~5區間的值全都改為v;

正常人的思維是把1~5這個區間的修改看成對點1,2,3,4,5的單點修改;但這樣的複雜度是nlog(n)是比較高的;

我們換一種想法,在修改區間的時候我們仍然像區間查詢一樣自上而下的尋找要修改的區間。那麼我們最後

找到區間是1~3和4~5這兩個區間。

我們把代表這兩個區間的節點的值進行修改;這樣一來我們就完成了區間修改;

但是這樣就會出現新的問題,我只是修改了這兩個節點的值,那麼如果我要查詢2~5區間的值的加和,按照區間查詢的步驟

我最後查詢的區間分別是2~2,3~3,4~5。可以發現只有4~5這個節點的值是正確的,2~2,3~3這兩個節點的值在區間修改的時候

沒有被修改。所以這樣查詢出來的值是錯誤的;

如何解決這個問題呢,我們發現區間修改所帶來的問題指揮影響區間查詢,所以我們可以修改一下區間查詢的邏輯。

我們在修改區間的同時把這個區間打一下標記,說明這個區間的子區間是沒有被修改的,在區間查詢的時候,如果

當前區間被標記過,我們就修改這個區間的子區間,並把這個標記下移到這個區間的子區間。這樣我們就解決了區間修改

的問題了;

**如下:

#include#include#define mmset(a,b) memset(a,b,sizeof(a))

#define lson l,m,rt<<1

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

const int inf = 1005;

int sum[inf << 2],mark[inf<<2]; //mark是用來標記的樹

void pushup(int rt) //向上更新

void pushdown(int l,int r,int rt) //將標記向下推移並修改兒子的值

return ;

}void update(int l,int r,int c,int l,int r,int rt) //區間更新

else }

int query(int l,int r,int l,int r,int rt) //區間查詢

else

}

這裡有道區間修改的題,感興趣的可以做一下

線段樹(區間修改+區間求和)

線段樹(2)區間修改

快速序列操作i,給出乙個n個元素的陣列a1,a2,an,你的任務是設計乙個資料結構支援一下兩種操作 set l,r,v 把al,al 1,ar的值全部修改為v v 0 query l,r 計算子串行al,al 1,ar的元素和 最小值和最大值。include include using namesp...

模板 線段樹(2)區間修改

好像叫做懶操作來著。還是叫延遲修改更高大上一點吧 區間修改 兩種操作 add l r v 把a l a l 1 a r 的值全部增加v query l r 計算子串行a l a l 1 a r 的元素和,最小值和最大值 修改 查詢的範圍均為 y1,y2 維護節點o,它對應區間 l,r void ma...

線段樹二(區間修改)

概述 區間修改即將乙個區間內所有值改為乙個值 或加上乙個值 為了執行快速,我們通常用 懶 標記維護整個區間值的情況,在需要是再將這個 懶 標記傳到該節點的兩個子節點上。模版 此為在整個區間上加上乙個值 洛谷p3372 include include include include include i...