直接放題目然後再進行解釋:
樹狀陣列:
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...