Binary Indexed Tree 樹狀陣列

2022-08-11 12:57:14 字數 2371 閱讀 6074

做leetcode 做到meetingroomii的時候我知道不用線段樹或者樹狀陣列是不太好搞了。還是來學習一下吧。

樹狀陣列算是線段樹的一種特殊情況(子集),所以樹狀陣列能解決的問題線段樹一定能做,但線段樹能做的樹狀陣列不一定能做。

對乙個陣列進行如下操作

update(i1,i2,operation)

求 value(i)=?

例如:int ar=new int[n]

update(ar,2,5,+,4) //(2 to 5).map(ar(_)+=4)

return ar(k)

對乙個陣列進行如下操作 update(index,operation,value)

求 sum(i1,i2)=?

例如:int ar=new int[n]

update(ar,3,+,5); //ar[3]+=5

update(ar,11,-,3); //ar[11]-=3

。。。。。。

求:sum(ar,0,12)? //(0 to 12).map(ar(_)).sum

應用線段樹的思路,對問題1,可以在中間節點快取操作o(lgn),求解時再計算出結果。

對問題2,可以直接快取sum,每次操作時都對sum附帶進行操作o(lgn),而求結果時,直接使用快取的sum結果o(lgn)。

按照剛才的解題分析,應當使用線段樹進行操作,但線段樹操作效率比較低,是否一種折中的辦法呢?

例如:把線段樹的每個節點對映到乙個額外的陣列上?

那麼問題很明確,如何將一顆有n個葉子節點的樹對映到乙個長度為n的陣列上?

最直觀的思路顯然是這樣:

圖看上去很容易理解,我們希望將中間結果(12)(58)等存在另外乙個陣列b裡,剩下的問題只有乙個,怎麼把這些節點向陣列的index對映?而且這個對映顯然是演算法可描述的,這樣在計算時才能容易找到各個節點。

究竟怎樣想出來的這種對映方式已經不得而知,但的確是個很神妙的構想,這也是binary index tree的精髓了。

圖2中黃色的塊被廢棄了,如果用a->b表示a存入b則:

(1~2)->2

(1~4)->4

(5~6)->6

(1~8)->8

1->1

3->3

5->5

7->7

是不是有點規律了?

奇數點全部存原陣列值

偶書點k存入的位數與k&(-k)後面的0相關,由m個0就存了1如果希望計算(st,ed)的sum時,如何計算呢?直接計算st到ed之間的資料相當難算,但是

sum(st,ed)=sum(1,ed)-sum(1,st-1)
這時候再看一下圖2是不是明白了?

從新定義乙個函式sumfromstart(k)表示從1加到k的和。

sum(st,ed)=sumfromstart(ed)-sumfromstart(st-1)
最後看看這個sumfromstart寫法吧其實很容易想到:

如果我們想算1~7

7=111=100+10+1

而且17=(14)+(5~6)+7

所以sumfromstart(7)=b(4)+b(6)+b(7)

再寫清楚點,如果是二進位制:

sumfromstart(111)=b(100)+b(110)+b(111)

想明白了? 還沒有?那就看圖吧

所以,sumfromstart(k)定義如下

int sumfromstart(int k,int b)

}

最後還有乙個更新操作,因為是單個更新,所以注意要把上面的點也更新了,以對a[5],操作為例,需要更新b(5),b(6),b(8)。寫出來這三個

b(101)

b(110)

b(1000)

看不出啥太明顯的規律啊?

101 +1 =110

110 +10=1000

明白了麼? k+k&(-k)啊,所以update寫出來

void update(int index,int v,operation=add,int b)

void updatefromstart(int index,int added,int b)

int bis=new int[ed-st+5];

int delta=st-1;

for(interval in:ins)

int max=0;

for(int i=1;i0)

}

數星星 樹狀陣列

題目描述 天空中有一些星星,這些星星都在不同的位置,每個星星有個座標。如果乙個星星的左下方 包含正左和正下 有 k 顆星星,就說這顆星星是 k 級的。例如,上圖中星星 5 是 3 級的 1,2,4 在它左下 星星 2,4 是 1 級的。例圖中有 1 個 0 級,2 個 1 級,1 個 2 級,1 個...

數星星(樹狀陣列)

天空中有一些星星,這些星星都在不同的位置,每個星星有個座標。如果乙個星星的左下方 包含正左和正下 有 k 顆星星,就說這顆星星是 k 級的。例如,上圖中星星 5 是 3 級的 1,2,4 在它左下 星星 2,4 是 1 級的。例圖中有 1 個 0 級,2 個 1 級,1 個 2 級,1 個 3 級的...

Sequence II(hdu5147)樹狀陣列

sequence ii 題意 在陣列中找到符合這個的條件的數的的個數 1.1 a b cn 2.a a ab 3.ac 思路 對乙個在位置i的數,用樹狀陣列就能知道前面比它小的數,類似地,找到後面比他小地數 根據後面比他小的數這個進行打表記錄在這個位置後能夠符合的對數 相乘一下就行了 include...