樹狀陣列理解

2021-09-14 01:20:46 字數 1453 閱讀 1977

無意間看到樹狀陣列,查了很多資料被各種圖和公式繞暈了,下面記錄一點個人理解。

假設陣列a[0],a[1],a[2],.....,a[n],記0-m元素之和為sum(m) (0=當我們頻繁的求s(m)時,第一種方法不適用,當我們頻繁的修改陣列a時,第二種方法每次都要修改陣列s,修改陣列s的時間複雜度為o(n)

而樹狀陣列可以很好解決這種場景,它類似方法二

方法二中我們定義s[m] = a[m]+a[m-1]+a[m-2]+....+a[0]

樹狀陣列中我們定義s[m]= a[m-1]+a[m-2]+....+a[i-2^k],其中k為m的二進位制的第乙個1前0的個數

ps:有些資料是m至i-2^k+1,那是陣列下標從1開始計數的,這裡下標從0開始,因此有所區別

舉個例子:10的二進位制1010,因此k=1;24的二進位制11000,因此k=3

我們記lowbit(m)=2^k,即有lowbit(10)=2,lowbit(24)=8

可以發現2的二進位制是10,8的二進位制是1000,因此lowbit的實現很簡單

static int lowbit (int x)
如果這方法無法理解,建議看下二進位制補碼

接下來陣列s就有的乙個公式

s[m]=a[m-1]+a[s-2]+....+a[i-lowbit(m)]

我覺得樹狀陣列講到這裡就可以了,為了便於理解,我舉乙個例子,測試**如下

public static void main(string args) 

}public static string intbinarystring(int i)

public static string intfixedstring(int i)

列印結果

假設求sum(28),我們分析一下 i = 28 binary i = 00011100 lowbit = 4 i-2^k = 24

s[28]=a[27]+a[26]+....+a[24]

其中最後乙個數是24,繼續分析 i = 24 binary i = 00011000 lowbit = 8 i-2^k = 16

s[24]=a[23]+a[22]+....+a[16]

最後乙個數是16,繼續分析 i = 16 binary i = 00010000 lowbit = 16 i-2^k = 0

s[16]=a[15]+a[14]+....+a[0]

很容易發現sum(28)=a[28]+s[28]+s[24]+s[16],**實現如下

public int sum(int m)  

return sum;

}

上面只是我的個人理解,如有錯誤,敬請指正。

參考:

樹狀陣列理解

c i 代表 子樹的葉子結點的權值之和 如圖可以知道 c 1 a 1 c 2 a 1 a 2 c 3 a 3 c 4 a 1 a 2 a 3 a 4 c 5 a 5 c 6 a 5 a 6 c 7 a 7 c 8 a 1 a 2 a 3 a 4 a 5 a 6 a 7 a 8 再將其轉化為二進位製看...

樹狀陣列原理解析

我們知道,對長度為n的陣列,如果我們要改變其中某個值,則時間複雜度為o 1 如果要求出s m a 1 a 2 a m 則需要o m 的時間複雜度。若我們一邊修改陣列的值,一邊要求求出其部分和s m 使用一般的方法,時間複雜度是o m n 的,若m和查詢次數n很大,那麼該演算法將不可取。為了解決這個問...

深入理解樹狀陣列

先上模板 單點更新const int n 1003 int n int a n void update int i,int d intgetsum int i 區間更新const int n 1003 int n int a n void update int i,int d intgetsum i...