二叉索引樹(樹狀陣列)

2021-07-29 22:44:57 字數 1846 閱讀 6370

二叉索引樹 (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,我們定義lowbit(x)為x的二進位制表示式中最右邊的1所對應的值。例如,38288的二進位制是:1001010110010000,所以lowbit(x) = 16(二進位制為10 000)。在程式實現中,lowbit(x) = x & (-x)。 因為計算機裡的整數採用補碼便是,因此-x實際上是x按位取反,末尾加1以後的結果。如下圖

兩者按位取「與」之後,前面部分全部為零,之後lowbit保持不變(都是第五位)。

下圖是一棵典型的bit,由十五個節點組成,編號為1 - 15.

灰色結點是bit中的結點(白色長條的含義稍後敘述),每一層結點的lowbit相同,而且lowbit越大,越靠近根。圖中的虛線是bit中的邊。

編號為0的點是虛擬結點,他並不是樹的一部分,但是他的存在可以讓

演算法理解起來更容易一些。

對於結點i,如果它是左子結點,那麼父結點的編號是i+lowbit(i)。如果它是右子結點,那麼父結點的編號是i-lowbit(i)。搞清楚樹的結構之後,構造乙個輔助陣列c,其中c[i]=a[i-lowbit(i)+1]+a[i-lowbit(i)+2]+....+a[i]。換句話說,c的每個元素都是a陣列中的一段連續和。到底是那一段呢?在bit中,每個灰色結點i都屬於乙個以它自身結尾的水平長條(對於lowbit=1的那些點,長條就是他本身),這個長條中數之和就是c[i]。其中

c[i] = a

i-lowbit(x)

+1 + a

i-lowbit(x)+2

+...+ai;

所以,有了c陣列,就可以計算si 了,其實只要節點i往左上「爬」就可以了,如下圖

所以相應**如下:

int sum(int x)

return ans;

}

而如果要修改ai,則應該順著i點往右走,為什麼?因為i點的改變會引起其父親節點的改變。如下圖

所對應的**為:

void add(int x,int d)

}

所以到最後我們就可以計算a1+a2+...+ai,並且修改某ai的值。

下面是一道練習題;

codevs p1080;

ac**如下:

/*

題目:p1080 線段樹練習

*/#includetypedef long long ll;

ll c[100000+10],n,m;

inline int lowbit(int x)

int sum(int x)

return res;

}void add(int x,int a)

}int main()

scanf("%d",&m);

while(m--)

return 0;

}

樹狀陣列(二叉索引樹)

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

二叉索引樹(樹狀陣列)

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

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

powered by phantom lsh將上面的求連續和問題稍微改進一下,現在需要支援一種新的操作 add x d 即把a x 增加d。這樣一來,如果通過字首和的方式計算就不能簡化計算了,因為每次修改乙個元素都要修改所有在它後面的字首和。有什麼解決辦法呢?我們需要用一種新的資料結構 bit二叉索...