這篇筆記 會詳細的講解,使得隊員們對樹狀陣列徹底入門 而不是懵懵懂懂。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的含義與上面相同 理解一下
下面說**
**c[i]=a[i-2^k+1]+a[i-2^k+2]+……a[i];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-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)];
細細觀察二進位制 樹狀陣列追其根本就是二進位制的應用
結合**
對於i=7 進行演示int getsum(int x)
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,所以它的...