線段樹 成段更新區間操作

2021-06-28 12:38:45 字數 1421 閱讀 2400

poj一道區間更新的**,區間加值。

#include #include #include #include #include using namespace std;

#define lson l,m,rt<<1

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

const int maxn=100010;

__int64 sum[maxn<<2];

__int64 lazy[maxn<<2];

void pushup(int rt)

void pushdown(int rt ,int m)

}void build(int l,int r,int rt)

int m=(l+r)/2;

build(lson);

build(rson);

pushup(rt);

}void update(int l,int r,int v,int l,int r,int rt)

pushdown(rt,r-l+1);

int m=(l+r)/2;

if(l<=m)

update(l,r,v,lson);

if(r>m)

update(l,r,v,rson);

pushup(rt);

}__int64 query(int l,int r,int l,int r,int rt)

pushdown(rt,r-l+1);

int m=(l+r)/2;

__int64 ret=0;

if(l<=m)

ret+= query(l,r,lson);

if(r>m)

ret+= query(l,r,rson);

return ret;

}int main()

else}}

return 0;

}

幾個細節:

1.

if(l<=m)

update(l,r,v,lson);

if(r>m)

update(l,r,v,rson);

有兩種寫法,也可以寫成其他形式,思想就是目標區間在當前區間左邊,在右邊,橫跨。

而我用的這個方式省略為兩種,思想是一樣的。

if(l<=l&&r<=r)

其實就是l==l&&r==r,因為要return了。

3.別人部落格中一些其他風格的線段樹用到了結構體,其實可以在query()和update()中用多傳幾個引數的方式代替,沒必要使用結構體。

4.不要忘記每次操作後pushdown()或者pushup()的使用。

5.對於sum和lazy要用到__int64。防止有些資料超出範圍,因為要用到線段樹肯定是稍微大一點資料量和資料範圍。

UESTC 1546(線段樹,成段更新,區間合併)

這個題有一點非常重要,就是任意乙個非法的序列,我們在它的左邊新增若干個 右邊新增若干個 那麼一定能夠變成乙個合法的序列。在這裡就不證明了,比如 我們在它的左邊新增兩個 右邊兩個 序列變成 就成了乙個合法的序列了!因此在每乙個區間,我們記錄它缺少的左括號數needl,缺少的右括號數needr,那麼區間...

POJ 3468 線段樹(成段更新,區間求和)

這個線段樹運用了應用了add域優化,每個節點除了用value記錄當前節點對應區間元素的和之外,還要用add域記錄當前節點對應區間每個元素的增量。這樣,沒必要每次更新都要更新value更新到最底層每乙個點,只需要將增量記錄在某父節點的add域中即可,如果下次查詢或者更新操作的是該父節點對應區間的子區間...

線段樹 區間更新 區間查詢

題意 題解 如果採用單點更新的思路對區間進行更新的話時間複雜度會比較高,因此用了乙個lazy陣列 俗稱懶人標記 它為什麼叫懶人標記呢,比如更新的區間為 l,r z,而l到r覆蓋了線段樹某乙個節點的區間,那麼可以將該節點對應的lazy陣列的值加上z,同時更新該節點的值,這樣就可以避免更新它子孫節點的值...