線段樹(區間查詢,區間修改) 標記永久化版

2022-05-20 01:03:00 字數 1817 閱讀 8272

傳送門:

為了不下傳add的標記,改為在詢問的過程當中計算每個遇到的節點對當前詢問的影響。而為了保證詢問的複雜度,子節點的影響需要在修改操作時計算好。因此實際上,add的值表示這個區間共同加上的值,seg表示這個區間內除了add之外其它數的值的和。需要注意,區間的add值可能有一部分在祖先節點上,這在遞迴時累加即可。

1 #include2

using

namespace

std;

3long

long

n,m;

4long

long num[500009

]; 5

long

long seg[500009];//

線段樹上除了add之外的值

6long

long add[500009];//

當前區間共同加上的值

7 inline long

long

read()811

while(ch>='

0'&&ch<='9')

12return x*f;13}

14 inline long

long ls(long

long x)//

左兒子

15 inline long

long rs(long

long x)//

右兒子

16void build(long

long now/*

現在所在的節點

*/,long

long l,long

long r/*

它所在的原數列區間*/)

1723

long

long mid=(l+r)>>1

;24 build(ls(now),l,mid); //

建立左兒子

25 build(rs(now),mid+1,r); //

建立右兒子

26 seg[now]=seg[ls(now)]+seg[rs(now)];//

當前節點為其左右兒子的值之和 27}

28void modify(long

long now/*

當前節點

*/,long

long l,long

long r/*

當前區間[l,r]

*/,long

long x,long

long y,long

long v)//

給定區間[x,y]所有數加上v

2935 seg[now]+=(min(r,y)-max(l,x)+1)*v;//

計算子節點對當前節點的影響

36long

long mid=(l+r)>>1;37

if(x<=mid)modify(ls(now),l,mid,x,y,v);

38if(mid1

,r,x,y,v);39}

40long

long query(long

long now,long

long l,long

long r,long

long x,long

long y)//

詢問區間[x,y]的和

4149

intmain()

5056 build(1,1,n);//

建立線段樹

57for(int i=1;i<=m;i++)

5865

if(pan==2)66

70}71 }

線段樹(區間修改 區間求和)lazy標記版

無lazy標記版 線段樹lazy標記模板題void push down int p,int lf,int rt 如果當前區間被標記但還要繼續遞迴下去,只需在下一次遞迴開始之前push down,向下標記子節點即可。區間修改 void update int p,int lf,int rt,int l,...

線段樹(點查詢 區間查詢 區間修改)模板

簡單記錄一下自己的 以後方便複習 其實有了這樣子的乙個模板,題目變式自己改改就可以,比如說加減變成乘除等等。pragma gcc optimize 3,ofast inline include include include include include include include inclu...

C 線段樹 區間修改 區間查詢

這次要引入乙個核心變數 lazy 懶標記 為了達到區間修改的目的 又為了減少運算量 所以就需要引入懶標記這個變數 用來滿足 即用即推 子線段要用了便向下推行 lazy 舉個例子 如果我們只用紅色這個線段 那就不用向下推 把 lazy 留在這裡 但是如果要用到橙色的部分 那就需要把 lazy 下推到橙...