BIT二叉索引樹(樹狀陣列)

2021-07-25 10:48:02 字數 2164 閱讀 3725

powered by phantom_lsh將上面的求連續和問題稍微改進一下,現在需要支援一種新的操作:add(x , d) 即把a[x]增加d。

這樣一來,如果通過字首和的方式計算就不能簡化計算了,因為每次修改乙個元素都要修改所有在它後面的字首和。有什麼解決辦法呢?我們需要用一種新的資料結構——bit二叉索引樹(樹狀陣列)。

在介紹二叉索引樹之前必須要介紹這樣乙個函式:lowbit(x),它返回的是正整數x的二進位制表示方法中最靠右的乙個1所代表的數字(例如:lowbit(10) = 2,因為10的二進位制是1010,最靠右的乙個1在第二位上,代表2)。

其實,lowbit看似複雜其實**實現異常簡單。即:

int lowbit ( int x)
它的原理其實是:在計算機內部,負數(-x)是x按位取反(1變0,0變1)然後加1之後的結果(這裡不討論為什麼),所以,-10的儲存其實是0110 。然後再進行與運算,就可以得到lowbit了。

終於進入了正題。運用lowbit我們可以把從1到n一段數字沿lowbit從大到小一半一半的分割開。比如:1-10中,8的lowbit最大,所以1-7一段,9-10一段,以此類推。所以,好像線段樹那樣,一段連續的數字被不停地分割直到只剩下乙個數字。

我們把lowbit相同的節點放在同一層(沒有的補上去),這樣自然形成一棵結點數為大於n的 最小的 2的某整數次方-1 的一棵完全二叉樹,其根結點為lowbit最大的結點。通常我們把0也變成乙個虛擬化的節點放在裡面,方便運算。

我們發現乙個重要的結論:由於lowbit的定義,每個結點的兩個子結點與該結點的二進位制只有兩位不同,一位是該節點的lowbit,兩個子結點分別為0和1,另一位是子結點的lowbit,兩個子結點都為1但是該結點為0 。這樣的現象產生乙個重要性質,即:***對於乙個結點x,它左上方(可以不是順著邊,而是首個向左上回溯的祖先結點)結點的編號為x-lowbit(x),而右上方(解釋同上)結點的編號為x+lowbit(x) 。***請打草稿或者仔細思考一下這個結論。

因此,我們可以不要儲存這一棵樹,因為邊的關係可以直接計算。另:在bit中只需要向上回溯。

一定要記住,bit的結點儲存的是原來的序列的下標!切記!!

那麼,bit已經構造出來了,怎麼用來解決問題呢?

現在,構造輔助陣列c[n](就像上面的s[n]一樣),c[x] = a[x-lowbit(x)+1]+a[x-lowbit(x)+2]+a[x-lowbit(x)+3] + ……+a[x](a陣列是原來的序列) 。這是什麼意思呢?請看圖:

每個結點都對應乙個向左延伸的黃顏色的橫條。橫條所覆蓋的數對應的序列值的和記錄在c陣列裡面,就好像字首和一樣。

那麼,c陣列有什麼用呢?

其實,如果要查詢乙個結點x的字首和,只要不停地順著x = x-lowbit(x) 迭代到0,將沿途的c陣列的值全部相加就可以得到a[1]+a[2]+……+a[x]了。在上圖中,就是順著藍色的箭頭不停地向左上方移動,觀察一下,是不是通過黃色的橫條不重複不遺漏的覆蓋了所有的下標?這就是查詢操作了。

那麼增加的操作呢?觀察發現,只要沿著x = x+lowbit(x)不停地向右上方走(圖上的紅色箭頭),直到走出邊界,修改沿途的c值就可以了(使它們增加d)。因為能夠覆蓋到結點x的黃色橫條只有那些。修改操作也就這樣完成了!

最後再說一下預處理,預處理只要把a陣列和c陣列都清空,然後執行n次add操作,相當於從0開始add到原始資料就可以了!

看上去說的很多,其實**實現很簡單,下面附上c++版本的sum函式(字首和)和add函式**。

int sum(int x)

return ans;

}void add(int x, int d)

return ;

}

最終,要求[a , b]的連續和只需要求sum(b) - sum(a-1)就可以了!

由於二叉樹的基本特徵,很容易看出修改和查詢字首和兩個函式的時間複雜度都是o(logn),而預處理是n次add操作,所以預處理時間複雜度是o(nlogn) 在查詢量多時遠遠優於暴力演算法!

powered by phantomlsh

二叉索引樹(樹狀陣列)

二叉索引樹 binary indexed tree,bit 動態連續和查詢問題,給定乙個n個元素的陣列a1,a 2,an。支援以下兩種操作 1.add x,d 操作 讓a x增加d。2.query l,r 計算al a l 1 ar。在學習二叉索引樹之前,需要先介紹lowbit.對於正整數x,我們定...

樹狀陣列(二叉索引樹)

樹狀陣列的原理介紹可見劉汝佳 演算法競賽入門經典 訓練指南 194頁,講的非常好 簡單自己對樹狀陣列的基本理解 我們原先不是把陣列看成一排嗎,但現在不是了,我們用乙個類似二叉樹的結構來儲存資料,存到c當中去,好好研究劉汝佳所畫的圖。下面說明基本應用 對於乙個n元素的陣列a n 可執行如下操作 add...

二叉索引樹(樹狀陣列)

二叉索引樹 binary indexed tree 又叫樹狀陣列,主要是用於解決動態連續和查詢問題。給定乙個n個元素的陣列a1,a2,an,你的任務是設計乙個資料結構,支援以下兩種操作。對於正整數x,我們 定義lowbit x 為想的二進位制表示式中最右邊所對應的值。比如由38288的二進位制是10...