樹狀陣列更新和求連續和

2021-07-04 21:24:40 字數 2738 閱讀 9533

1.「樹狀陣列」資料結構的一種應用

對含有n個元素的陣列(a[1],...,a[k],...,a[n]):

(1)求出第i個到第j個元素的和,sum=a[i]+...+a[j]。

進行j-i+1次加法,複雜度為o(j-i+1)

(2)任意修改其中某個元素的值。

使用陣列下標可以直接定位修改,時間複雜度為o(1)

對於同時支援上述兩種操作的系統中,求和操作(1)求任意連續個陣列元素和的平均時間複雜度為o(n),修改操作(2)時間複雜度是o(1)。如果系統中大量進行上述兩種操作m次,其中執行操作(1)概率1/p,操作(2)概率1-1/p,則系統時間複雜度為:

可以使用樹狀陣列使得上述兩種操作的時間複雜度為o(m*logn)

2.樹狀陣列介紹

核心思想:

(1)樹狀陣列中的每個元素是原陣列中乙個或者多個連續元素的和。

(2)在進行連續求和操作a[1]+...+a[n]時,只需要將樹狀陣列中某幾個元素的和即可。時間複雜度為o(lgn)

(3)在進行修改某個元素a[i]時,只需要修改樹狀陣列中某幾個元素的和即可。時間複雜度為o(lgn)

下圖就是乙個樹狀陣列的示意圖:

解釋如下:

1) a:儲存原始資料的陣列。(操作(1)求其中連續多個數的和,操作(2)任意修改其中乙個元素)

e:樹狀陣列,其中的任意乙個元素e[i]可能是乙個或者多個a陣列中元素的和。如e[2]=a[1]+a[2]; e[3]=a[3]; e[4]=a[1]+a[2]+a[3]+a[4]。 

2) e[i]是幾個a陣列中的元素的和?

如果數字 i 的二進位制表示中末尾有k個連續的0,則e[i]是a陣列中2^k個元素的和,則e[i]=a[i-2^k+1]+a[i-2^k+2]+...+a[i-1]+a[i]。

如:4=100(2)  e[4]=a[1]+a[2]+a[3]+a[4];

6=110(2)  e[6]=a[5]+a[6]

7=111(2)  e[7]=a[7]

3)後繼:可以理解為節點的父親節點。

離它最近的,且編號末位連續0比它多的就是它的父親,如e[2]是e[1]的後繼;e[4]是e[2]的後繼。

e[4] = e[2]+e[3]+a[4]= a[1]+a[2]+a[3]+a[4] ,e[2]、e[3]的後繼就是e[4]。

後繼主要是用來計算e陣列,將當前已經計算出的e[i]新增到他們後繼中。

前驅:節點前驅的編號即為比自己小的,最近的,最末連續0比自己多的節點。如e[7]的前驅是e[6],e[6]的前驅是e[4]。

前驅主要是在計算連續和時,避免重複新增元素。

如:sum(7)=a[1]+...+a[7]=e[7]+e[6]+e[4]。(e[7]的前驅是e[6], e[6]的前驅是e[4])

計算前驅與後繼:

lowbit(i) = ( (i-1) ^ i) & i ;

節點e[i]的前驅為 e[ i - lowbit(i) ];

節點e[i]的後繼為 e[ i + lowbit(i) ]

3.樹狀陣列**示例

1 #include 2 #include 3

4using

namespace

std;56

int input(int*,int*,int); ///

輸入資料

7int calstagesum(int*,int); ///

計算樹狀陣列

8int getsum(int*,int); ///

求出前n個數字的和

9int updataelement(int*,int*,int,int,int); ///

更新某一位置上的元素

1011

intmain ()

3637

int input(int* num,int *sum,int

n)42

return0;

43}4445

int calstagesum(int *sum,int

n)54}55

return0;

56}5758

int getsum(int* sum,int

n)66

return

sumpren;67}

6869

int updataelement(int* sum,int *num,int n,int pos,int

newvalue)

81else

82break;83

}84return0;

85 }

C 動態求連續區間和(樹狀陣列)

給定 n 個數組成的乙個數列,規定有兩種操作,一是修改某個元素,二是求子數列 a,b 的連續和。輸入格式 第一行包含兩個整數 n和 m,分別表示數的個數和操作次數。第二行包含 n個整數,表示完整數列。接下來 m行,每行包含三個整數 k,a,b k 0,表示求子數列 a,b 和 k 1,表示第 a 個...

poj3468 樹狀陣列的區間快速更新和查詢

直接用樹狀陣列會超時 所以必須快速更新。分析 由於本題更新的時候是區間更新 所以不能直接去乙個個更新區間內的點,肯定會超時 對於每次更新c a,b,d 表示區間 a,b 內的值增加d 用ans a 表示a n區間元素增加的值,所以對於c a,b,d 有 ans a d,ans b 1 d 則每次詢問...

動態求連續區間和 樹狀陣列與線段樹

樹狀陣列,這玩意吧,我也整不明白具體的原理,說的好聽點就是注重實踐,說不好聽點就是揹著這幾個函式會寫就行了 給定 n 個數組成的乙個數列,規定有兩種操作,一是修改某個元素,二是求子數列 a,b 的連續和。輸入格式 第一行包含兩個整數 n 和 m,分別表示數的個數和操作次數。第二行包含 n 個整數,表...