演算法 樹狀陣列

2022-08-22 12:42:09 字數 1280 閱讀 3178

要學樹狀陣列的先看懂一幅圖

這就是樹狀陣列的儲存方式。

那麼樹狀陣列的優點是什麼呢,允許任意修改,可快速提取出a陣列內數字

據圖可知

c1=a1,

c2=a1+a2,

c3=a3,

c4=a1+a2+a3+a4,

c5=a5,

c6=a5+a6,

c7=a7,

c8=a1+a2+a3+a4+a5+a6+a7+a8,

c9=a9,

c10=a9+a10,

c11=a11.......

.c16=a1+a2+a3+a4+a5+.......+a16。

分析上面的幾組式子可知,當 i 為奇數時,ci=ai ;當 i 為偶數時,就要看 i 的因子中最多有二的多少次冪,例如,6 的因子中有 2 的一次冪,等於 2 ,所以 c6=a5+a6(由六向前數兩個數的和),4 的因子中有 2 的兩次冪,等於 4 ,所以 c4=a1+a2+a3+a4(由四向前數四個數的和)。

(一)因此得到公式    cn=a(n-a^k+1)+.........+an(其中 k 為 n 的二進位制表示中從右往左數的 0 的個數)。

那麼,如何求 a^k 呢?求法如下:

1int lowbit(intx)2

為啥那?

以68為例,他的二進位制是(68)2=1000100. 那麼-68呢?因為計算機裡的整數採用補碼表示(補碼是原碼取反加一),因此-68實際上是68按位取反,末尾加一以後的結果。如下表(忽略符號位):

原碼   1 0 0 0 1 0 0

↓反碼   0 1 1 1 0 1 1

↓補碼   0 1 1 1 1 0 0

我們把(68)2和(-68)2放在一起看一看:

1 0 0 0 1 0 0

0 1 1 1 1 0 0

發現他們末尾帶的0是一樣多的。因此lowbit(x)=x&-x.   (&是轉換成二進位制之後進行與運算;而&&是直接進行與運算)

(二)由此,我們就可以求出c陣列了

1

int sum(intx)2

9 }

(三)當陣列中的元素有變更時,樹狀陣列就發揮它的優勢了,演算法如下(修改為給某個節點 i 加上 x ):

1

void change(int i,intx)2

8 }

嗯。就這樣。不算難。大概就是一種可變更的儲存方式吧

演算法 樹狀陣列

演算法適用於求前k個整數的和,一般的做法是設定乙個sum陣列來表示 1 問題公升級一下 在查詢的過程中隨時給第x個整數加上乙個整數v,同樣要求查詢第k個整數的和。此時若還是原來的sum陣列,則要遍歷來更新,複雜度為o n 而用樹狀陣列則時間要更快。2 再來一題 很簡單的,別怕昂 計算序列中在元素左邊...

演算法 樹狀陣列

相信大家都會樹狀陣列的 單點修改,區間查詢 或者 區間修改,單點查詢 博主就不細講了。但是博主今天發現了乙個神奇的演算法 博主太菜 它可以使用樹狀陣列維護 區間修改,區間查詢 就是乙個優化過的字首和,使查詢和修改協調為 theta log 2n namespace fentree void add ...

演算法(十三)樹狀陣列

問題描述 小蔥喜歡除法,所以他給了你n個數a1,a2,an,並且希望你執行m次操作,每次操作可能有以下兩種 給你三個數l,r,v,你需要將al,al 1,ar之間所有v的倍數除以v。給你兩個數l,r,你需要回答al al 1 ar的值是多少。輸入格式 第一行兩個整數n,m,代表數的個數和操作的次數。...