練習 2 樹狀陣列 模板二(區間修改,單點查詢)

2021-10-18 11:50:40 字數 2185 閱讀 7928

直接放題目然後再進行解釋:

樹狀陣列:

1.單點修改,區間查詢

2.區間修改,單點查詢

3.區間修改,區間查詢

description

給定數列a[1],a[2],…,a[n] ,你需要依次進行 q 個操作,操作有兩類:

1 l r x:給定 l,r,x,對於所有i∈[l,r],將 a[i] 加上 x(換言之,將 a[l],a[l+1],…,a[r] 分別加上 x);

2 i:給定 i ,求 a[i] 的值。

input

第一行包含 2 個正整數 n,q,表示數列長度和詢問個數。保證1≤n,q≤106 。

第二行 n 個整數 a[1],a[2],…,a[n],表示初始數列。保證|a[i]|≤106 。

接下來 q 行,每行乙個操作,為以下兩種之一:

1 l r x:對於所有 i∈[l,r],將a[i]加上x;

2 i:給定 i,求 a[i] 的值。

保證 1≤l≤r≤106, |x|≤106。

output

對於每個 2 i 操作,輸出一行,每行有乙個整數,表示所求的結果。

samples

input

3 21 2 3

1 1 3 0

2 2output

2hint

對於所有資料,1≤n,q≤106 , |a[i]|≤106, 1≤l≤r≤n, |x|≤106

#include

using

namespace std;

typedef

long

long ll;

inline

intread()

while

('0'

<= ch && ch <=

'9')

return x * f;

}int n,q,a,b,c,k,x,now,last;

ll t[

1000005];

ll lowbit

(ll x)

void

add(ll x,ll w)

return;}

ll sum

(ll x)

return s;

}int

main()

while

(q--)if

(k==2)

}return0;

}

前面的三個函式lowbit,add,sum和單點修改,區間查詢是一樣的,不再多做解釋,可以在上乙個練習檢視。

要做到區間修改,我們能想到的省時間的做法是什麼—差分字首和

打個比方,也就是說我們要給區間[1,3]的每個數加上4,我們只需要給差分陣列的a[1]加上4,給差分陣列的a[4]減去4

a[1]

+=4;a[4]

-=4;

這是因為差分在做字首和的時候就會給每個數都加上這個數(4,0,0,-4 --> 4,4,4,0)

for

(ll i=

1;i<=n;i++

)

最開始輸入的時候就要做好差分,確保這個陣列是乙個差分陣列

a=

read()

; b=

read()

; c=

read()

;add

(a,c)

;add

(b+1

,-c)

;

修改區間的時候也要做好差分,所以是兩個add。

x =

read()

;printf

("%lld\n"

,sum

(x))

;

最後要查詢哪乙個位置就直接輸出哪個位置的sum(x)。

因為我們在之前說過的(單點修改,區間查詢)sum函式最終得到的是字首和,那麼差分陣列的字首和,某個位置的值,就是該位置實際的值。

以上只是鄙人的拙見,如果有錯誤、不足之處,還請指正。

線段樹二(區間修改)

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

線段樹(二) 區間修改

上一節介紹了點修改與區間查詢的線段樹,事實上,線段樹還可以做得更多。本節討論區間修改問題。給出乙個 n 個元素的陣列 a 1,a 2,a n 你的任務是設計乙個資料結構,支援以下兩種操作 點修改只會影響到 logn 個結點,但區間修改在最壞情況下會影響到樹中的所有結點,比如,如果對整個區間執行 ad...

樹狀陣列 模板2 區間修改 單點查值

樹狀陣列的區間修改是基於差分的基礎之上 設陣列a 那麼差分陣列b 也就是說b i a i a i 1 a 0 0 那麼a i b 1 b i 假如區間 2,4 都加上2的話 a陣列變為a b陣列變為b 發現了沒有,b陣列只有b 2 和b 5 變了,因為區間 2,4 是同時加上2的,所以在區間內b i...