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

2022-07-17 10:33:10 字數 2481 閱讀 2036

這次要引入乙個核心變數:

lazy 懶標記

為了達到區間修改的目的

又為了減少運算量

所以就需要引入懶標記這個變數

用來滿足 即用即推

子線段要用了便向下推行 \(lazy\)

舉個例子:

如果我們只用紅色這個線段

那就不用向下推

把 \(lazy\) 留在這裡

但是如果要用到橙色的部分

那就需要把 \(lazy\) 下推到橙色部分

變數含義詳見上個bolg

void add(int i,int l,int r,int k)

if(tree[i].lazy != 0) push(i);

if(tree[li].r >= l)

add(li,l,r,k);

if(tree[ri].l <= r)

add(ri,l,r,k);

tree[i].sum = tree[li].sum + tree[ri].sum;

return ;

}

我們會發現這個函式會呼叫到 push函式

因此我先解釋一下 push函式 的作用:

將當前的 lazy標記 推到下一層

然後我們再來看**

這表示當前線段已經完全在範圍包裹裡了

對 \(sum\) 的操作:

把 \(k\) 的值分配到當前線段

有 \(tree[i].r - tree[i].l + 1\) 個數

那 \(k\) 就需要乘上 \(tree[i].r - tree[i].l + 1\)

對 \(lazy\) 的操作:

直接加上 \(k\)

要注意這裡的 \(lazy\) 是上一輪 add留下來的懶標記

(如果 \(lazy\) 不為 0 的話)

因為不需要向下推

所以在原來的基礎上直接加就行了

如果執行到這裡

說明區間和線段有交叉的部分

那我們就需要二分然後往下了

這時候 \(lazy\) 就不能再留在上一層了

需要用 \(push函式\) 把 \(lazy\) 推下去

怎麼推會在後面講 這裡可以先這樣理解

這裡二分向下推的操作和之前相同

便不再贅敘

當然 最後還需要吧 \(sum\) 的值更新

void push(int i)
前面有提到這個函式時用來下推 \(lazy\) 的

那這裡就來看看它是如何做到的

首先先把兩個子線段的 \(lazy\) 複製為當前線段的懶標記

再把 \(sum\) 給加上

然後讓線段的 \(lazy\) 歸為 0

int search(int i,int l,int r)
完全在區間內就直接返回 \(sum\)

如果要往下面搜尋

那就先要把 \(lazy\) 往下面推

然後在把這段的值加起來返回上去

#include#define maxn 1000010

#define inf 1e12

#define mid ((l+r)>>1)

#define li i<<1

#define ri 1+(i<<1)

using namespace std;

int n,val[maxn];

struct nodetree[maxn];

void read()

void build(int i,int l,int r)

build(li,l,mid);

build(ri,mid+1,r);

tree[i].sum = tree[li].sum + tree[ri].sum;

return ;

}void push(int i)

void add(int i,int l,int r,int k)

if(tree[i].lazy != 0) push(i);

if(tree[li].r >= l)

add(li,l,r,k);

if(tree[ri].l <= r)

add(ri,l,r,k);

tree[i].sum = tree[li].sum + tree[ri].sum;

return ;

}int search(int i,int l,int r)

void interaction() else if(tot == 2) else if(tot == 3) }}

int main()

線段樹單點修改區間查詢

這是一道模板題。給定數列 a 1 a 2 a n 你需要依次進行 qq 個操作,操作有兩類 1 i x 給定 i,x,將 a i 加上 x 2 l r 給定 l,r,求 ri la i 的值 換言之,求 a l a l 1 a r 的值 input 第一行包含 2 個正整數 n,q,表示數列長度和詢...

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

1547 例 1 區間和 時間限制 1000 ms 記憶體限制 524288 kb 提交數 2072 通過數 639 題目描述 給定一數列,規定有兩種操作,一是修改某個元素,二是求區間的連續和。輸入 輸入資料第一行包含兩個正整數n,m n 100000,m 500000 以下是m行,每行有三個正整數...

I Hate It 線段樹 單點修改 區間查詢

time limit 9000 3000 ms j a others memory limit 32768 32768 k j a others total submission s 40034 accepted submission s 15898 很多學校流行一種比較的習慣。老師們很喜歡詢問,從...