樹狀數組

樹狀數組定義:html

是一個查詢和修改複雜度都爲log(n)的數據結構。能夠用於處理前綴和的問題,動態維護前綴和的工具數組

區間修改和區間查詢用樹狀數組會顯得很麻煩 相對而言用線段樹會更靈活。數據結構

基本操做:求數列區間和,能夠對數列單點進行操做。ide

前置知識:工具

差分數組spa

lowbit()操做:返回非負整數x 在二進制表示下,第一個1和後面的0表示的數值(十進制的值)。3d

int lowbit(int x)
{
     return x&(-x);
}
/*
-i 表明i的負數 計算機中負數使用對應的正數的補碼來表示
k表示i的二進制中末尾連續0的個數。 例如 : i=6(0110) 此時 k=1 -i=-6=(1001+1)=(1010) i&(-i)=(0010)=2=2^K k=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];
*/

樹狀數組思想:code

區間查詢——》前綴和  ——》樹結構維護(log2n)htm

樹狀數組 t[x] 保存以x爲根的子樹中葉節值的和 。blog

觀察 t[x] 中每一個x的二進制,每一層末尾零相同 ,零的個數即K對應覆蓋的長度,覆蓋長度就是lowbit(x)。

 t [x] 的父節點爲 t【x+lowbit[x]】 樹的深度爲 log2n+1

 

 

基本操做(單點修改 查詢前綴和)

void update(int i,int val)//單點更新
{
    while(i<=n){
        t[i]+=val;
        i+=lowbit(i);//由葉子節點向上更新樹狀數組C,從左往右更新
    }
}
int ask(int x)//求區間[1,i]內全部元素的和 即求前綴和
{
    int ans=0;
    while(x>0){
        ans+=t[x];//從右往左累加求和
        x-=lowbit(x);
    }
    return ans;
}

   

樹狀數組初始化

memset(a, 0, sizeof a);
memset(c, 0, sizeof c);

cin>>n;

for(int i = 1; i <= n; i++){

   cin>>a[i];

   updata(i,a[i]); //輸入初值的時候,也至關於更新了值

 }

 

 樹狀數組的用法

1.單點修改,單點查詢    update(x,val) ;  ask(x) - ask(x-1);

2.單點修改,區間查詢     update(x,val) ;  ask(r) - ask(l-1);

3.區間修改,單點查詢  (差分數組 ) 

 用樹狀數組維護差分數組的前綴和,即原數列的每一個元素,因爲區間修改 ,產生的改變量。

 區間修改 [l,r]+d    update(l,d)   update(r+1,-d) 

 查詢 a[x]                ans =a[x]+ask(X) 

4. 區間修改,區間查詢 

   求出原數列a[x]的前綴和  ans=a[r]-a[l]   原數列的前綴和也能夠用差分數組來求 

 

 

 

 參考

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息