樹狀陣列徹底入門

2021-08-15 13:44:36 字數 3553 閱讀 3024

int lowbit(int t)

void add(int x,int y)

int getsum(int x)

這篇筆記 會詳細的講解,使得隊員們對樹狀陣列徹底入門 而不是懵懵懂懂。

以上先給出 最常見的,三個函式。(單點更新,區間查詢)

網上的解釋以及分析有很多,這裡是我的一點總結和體會歸納一下,並且在週三(2016.12.07)的講座之後會發布在團隊筆記中,

請隊員們細細閱讀,並且補題。

下面開始

***************************************分割線

樹狀陣列 重點是在樹狀的陣列

大家都知道二叉樹吧

葉子結點代表a陣列a[1]~a[8]

現在變形一下

現在定義每一列的頂端結點c陣列

如下圖

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];

下面觀察如下圖

將c陣列的結點序號轉化為二進位制

1=(001) c[1]=a[1];

2=(010) c[2]=a[1]+a[2];

3=(011) c[3]=a[3];

4=(100) c[4]=a[1]+a[2]+a[3]+a[4];

5=(101) c[5]=a[5];

6=(110) c[6]=a[5]+a[6];

7=(111) c[7]=a[7];

8=(1000) c[8]=a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8];

對照式子可以發現 c[i]=a[i-2^k+1]+a[i-2^k+2]+……a[i]; (k為i的二進位制中從最低位到高位連續零的長度)例如i=8時,k=3;

可以自行帶入驗證;

現在引入lowbit(x)

lowbit(x) 其實就是取出x的最低位1 換言之 lowbit(x)=2^k k的含義與上面相同 理解一下

下面說**

int lowbit(int t)

//-t 代表t的負數 計算機中負數使用對應的正數的補碼來表示

//例如 :

// t=6(0110) 此時 k=1

//-t=-6=(1001+1)=(1010)

// t&(-t)=(0010)=2=2^1

**c[i]=a[i-2^k+1]+a[i-2^k+2]+……a[i];

c[i]=a[i-lowbit(i)+1]+a[i-lowbit(i)+2]+……a[i];**

***************************************分割線

ok 下面利用c[i]陣列,求a陣列中前i項的和

舉個例子 i=7;

sum[7]=a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7] ; 前i項和

c[4]=a[1]+a[2]+a[3]+a[4]; c[6]=a[5]+a[6]; c[7]=a[7];

可以推出: sum[7]=c[4]+c[6]+c[7];

序號寫為二進位制: sum[(111)]=c[(100)]+c[(110)]+c[(111)];

再舉個例子 i=5

sum[7]=a[1]+a[2]+a[3]+a[4]+a[5] ; 前i項和

c[4]=a[1]+a[2]+a[3]+a[4]; c[5]=a[5];

可以推出: sum[5]=c[4]+c[5];

序號寫為二進位制: sum[(101)]=c[(100)]+c[(101)];

細細觀察二進位制 樹狀陣列追其根本就是二進位制的應用

結合**

int getsum(int x)

對於i=7 進行演示

7(111) ans+=c[7]

lowbit(7)=001 7-lowbit(7)=6(110) ans+=c[6]

lowbit(6)=010 6-lowbit(6)=4(100) ans+=c[4]

lowbit(4)=100 4-lowbit(4)=0(000)

對於i=5 進行演示

5(101) ans+=c[5]

lowbit(5)=001 5-lowbit(5)=4(100) ans+=c[4]

lowbit(4)=100 4-lowbit(4)=0(000)

***************************************分割線

當我們修改a陣列中的某乙個值時 應當如何更新c陣列呢?

回想一下 區間查詢的過程,再看一下上文中列出的圖

結合**分析

void add(int x,int y)

//可以發現 更新過程是查詢過程的逆過程

//由葉子結點向上更新c陣列

如圖:

當更新a[1]時 需要向上更新c[1] ,c[2],c[4],c[8]

c[1], c[2], c[4], c[8]

寫為二進位制 c[(001)],c[(010)],c[(100)],c[(1000)]

1(001) c[1]+=a[1]

lowbit(1)=001 1+lowbit(1)=2(010) c[2]+=a[1]

lowbit(2)=010 2+lowbit(2)=4(100) c[4]+=a[1]

lowbit(4)=100 4+lowbit(4)=8(1000) c[8]+=a[1]

***************************************分割線

先這樣

講解題目:

poj 2299

cf 703d

掌握樹狀陣列 徹底入門

大佬部落格 先貼一下樹狀陣列的模板 int lowbit int i void update int i,int val 單點更新 int sum int i 求區間 1,i 內所有元素的和 return ret 模板中最常見的三個函式 取陣列下標二進位製非0最低位所表示的值 單點更新 區間查詢。樹...

掌握樹狀陣列 徹底入門

先貼一下樹狀陣列的模板 int lowbit int i void update int i,int val 單點更新 int sum int i 求區間 1,i 內所有元素的和 return ret 模板中最常見的三個函式 取陣列下標二進位製非0最低位所表示的值 單點更新 區間查詢。樹狀陣列,顧名...

樹狀陣列1 樹狀陣列入門

仔細看一下,發現tree的每乙個節點的高度並不是隨意的,而是由它轉成二進位制之後末尾連續零的數量決定的,連續零的數量加1,就是高度,例如 3 11 零的數量為0,加1等於1,所以它的高度就是1 6 110 零的數量為1,加1等於2,所以它的高度就是2 8 1000 零的數量為3,加1等於4,所以它的...