上一次我們寫的線段樹已經可以解決區間查詢、單點修改了!可喜可賀
那如果現在我們需要區間修改、區間查詢呢?
一般有兩種思路:lazytag和標記永久化,lazytag的使用面好像更廣一些。
一、lazytag
比如我們現在要修改乙個區間,我們可以像查詢一樣分成若干段,然後分別修改每一段。
那麼問題來了,每一段要怎麼修改?如果直接修改sum,詢問就亂套了。如果暴力修改,最壞複雜度o(n),那還要線段樹幹嘛(╯‵□′)╯掀桌
那我們這麼想,我們修改就不修改整個區間了,而是在區間上維護乙個標記。
那我們查詢的時候要怎麼辦呢?我們一路走一路下傳標記,就是說把這個點的標記清掉,更新本節點的資訊,並把標記傳給兒子。
那這樣又有乙個問題,如果我們修改了乙個點的孩子,然後查詢的時候只查詢到上面的這個點,那資訊不就更新不到了嗎?
那我們查詢的時候還要用兒子節點的資訊順便更新一下本節點的資訊。
說了這麼多…寫起來好像還是蠻簡單的。
下面這份**的碼風比較奇怪…就是只建了滿二叉樹,沒有按n來建…**裡的ls和rs表示區間的左右端點…
//二、標記永久化codevs1082 區間加乙個數 區間查詢和
#include #include
#include
#include
#include
#include
#include
#include
using
namespace
std;
intn;
typedef
long
long
ll;#define sz 555555
int m=262144,m2=m+m,ls[sz],rs[sz];
ll sum[sz],tag[sz];
void
build()
void pd(intx)}
void upd(int
x)void edit(int x,int ql,int qr,int
v)
int mid=ls[x]+rs[x]>>1
; edit(x+x,ql,min(qr,mid),v);
edit(x+x+1,max(mid+1
,ql),qr,v);
upd(x);
}ll gsum(
int x,int ql,int
qr)int
q,a,b,c;
char buf[3
];void
readdata()
else
}}int
main()
你可能會覺得:lazytag使用起來很方便,感覺也很強大,為啥還要什麼標記永久化?
等你學了主席樹你就明白了 反正多學總沒有什麼問題233
標記永久化就是如果我們要修改乙個區間,還是在區間上打乙個標記,但是不下傳!
——啥,不下傳如何保證正確性?
我們在修改的路徑上更新這個區間的和,然後在返回和的時候把標記累加進去,這樣就可以保證正確性了。
//我相信你學完這兩種方法,線段樹的題都可以隨手秒啦!codevs1082 區間加乙個數 區間查詢和
#include #include
#include
#include
#include
#include
#include
#include
using
namespace
std;
intn;
typedef
long
long
ll;#define sz 555555
int maxn=524288
;ll sum[sz],tag[sz];
void edit(int x,int ql,int qr,int v,int l,int
r) sum[x]+=(qr-ql+1)*v;
int mid=l+r>>1
; edit(x+x,ql,min(qr,mid),v,l,mid);
edit(x+x+1,max(mid+1,ql),qr,v,mid+1
,r);
}ll gsum(
int x,int ql,int qr,int l,int
r)int
q,a,b,c;
char buf[3
];void
readdata()
scanf("%d
",&q);
while(q--)
else
}}int
main()
線段樹高階 區間取模
題目要求的操作 1 區間求和 2 區間取模 3 單點修改 這道題目不要用到 lazy陣列,因為條件是單點修改,直接修改的葉子節點,其次區間取模操作直接可以暴力。a mod b分為兩種情況 1 a b 2 a b 對於第一種情況 我們不用操作,對自己大的數取模就是自己。第二種情況 取模操作後a的值至少...
高階資料結構 線段樹
今天是很沉重的一天,進來ccf官宣取消oi,也不知道是不是真的。oier們不要放棄夢想!大家一定要勇往直前!這線段樹會很難 至少我是這麼想的 不過我也是經過百般實驗才敢寫這個部落格!假定我給你乙個定區間,讓你以最快的速度做這樣的操作 修改其中的乙個子區間,查詢另乙個子區間的值,而且重複這些操作。你會...
C 線段樹 高階資料結構
線段樹是一種平衡二叉搜尋樹 完全二叉樹 它將乙個線段區間劃分成一些單元區間。對於線段樹中的每乙個非葉子節點 a,b 他的左兒子表示的區間為 a,a b 2 右兒子表示的區間為 a b 2 1,b 最後的葉子節點數目為n,與陣列下標對應。線段樹的一般包括建立 查詢 插入 更新等操作,建立規模為n的時間...