樹狀陣列 詳解

2021-08-20 05:19:26 字數 1785 閱讀 2840

由圖可知,原始的陣列是a陣列,樹狀陣列是e陣列。通俗的說:

e[1]=a[1];

e[2]=a[1]+a[2];

e[3]=a[3];

e[4]=a[1]+a[2]+a[3]+a[4];

e[5]=a[5];

e[6]=a[5]+a[6];

e[7]=a[7];

e[8]=a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8];

為什麼是這樣的規律呢?這就涉及到2進製的問題了。我們首先看一下e[1],1的二進位制是1,有從後往前有0個連續的0,那麼,我們規定:e[1]就是從a陣列的1位置往前推2^0個數的和。我們再來看一下e[8],的二進位制位1000,從後往前有3個連續的0,那麼e[8]就是從a陣列的8位置往前推2^3個數的和,即:a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8]。我們最後看一下e[10],10的二進位制是1010,從後往前有1個連續的0,那麼e[10]就是從a陣列的10位置往前推2^1個數的和,即:a[9]+a[10]。

sum操作:求陣列的字首和。

int sum(int q)//求字首和(a陣列n位置到1位置上的數的和)

update操作:更新字尾和

void update(int i,int j)//當a陣列i位置上的數變化了j後,重新更新樹狀陣列c

#include#define maxn 9999

using namespace std;

string op;//指令

int a[maxn];//原始陣列

int c[maxn];//樹狀陣列

int n;//原始陣列的大小

int q;//查詢字首和時查詢從陣列1到q位置上的和

int z,l;//更新字尾和時原始陣列z位置變化了l

int lowbit(int n)//假如說n等於8,那麼8的2進製為:1000。函式返回的是2^3(二進位制中有從後往前連續的3個0),即:8。

int sum(int q)//求字首和(a陣列n位置到1位置上的數的和)

void update(int i,int j)//當a陣列i位置上的數變化了j後,重新更新樹狀陣列c

int main()

cin>>op;

if(op=="update")

if(op=="sum")

{cin>>q;

cout接下來講一下為什麼用樹狀陣列進行查詢字首和,更新陣列中的值這些操作會很快。

我們先想一下正常的求陣列字首和的操作:從陣列i位置往前遍歷到1位置,累加。時間複雜度為o(n)。用樹狀陣列:假如說求陣列前6項的和,只需要找到e[6]位置和e[4]位置,累加。就得到結果了。時間複雜度為o(log n)。很顯然快。

還是上面思路,我們先想一下正常的更新陣列中某個位置的值的操作:找到這個位置,更新。時間複雜度為o(1)。用樹狀陣列:假設陣列1位置上的數發生了變化,我們需要更新e[1],e[2],e[4],e[8](假設陣列大小是8),時間複雜度為o(log n)。比正常的操作的時間複雜度還高,但是你要兩種操作合起來看,樹狀陣列的整體時間複雜度是o(log n),而普通的方法是求字首和操作很慢,更新陣列中數的操作很快。還是選擇樹狀陣列比較好

樹狀陣列 詳解

對於普通陣列,其修改的時間複雜度位o 1 而求陣列中某一段的數值和的時間複雜度為o n 因此對於n的值過大的情況,普通陣列的時間複雜度我們是接受不了的。在此,我們引入了樹狀陣列的資料結構,它能在o logn 內對陣列的值進行修改和查詢某一段數值的和。假設a陣列為儲存原來的值得陣列,c為樹狀陣列。我們...

樹狀陣列詳解

樹狀陣列求區間和的一些常見模型 樹狀陣列在區間求和問題上有大用,其三種複雜度都比線段樹要低很多 有關區間求和的問題主要有以下三個模型 以下設a 1.n 為乙個長為n的序列,初始值為全0 1 改點求段 型,即對於序列a有以下操作 修改操作 將a x 的值加上c 求和操作 求此時a l.r 的和。這是最...

樹狀陣列詳解

比如說,我這裡有一組數1,2,3,2,k。我想知道第i到第j的和 mathop sum limits j v i 是多少?樸素演算法 for int k 0 k n k if k i k j ans v k 類似這種的寫法,雖然在某些點值改變時也依然可以計算 我們稱這種問題為動態問題 但複雜度最高到...