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 34using
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 個整數,表...