樹狀數組

樹狀數組(binary indexed tree)
概念:是一種數組結構
目的:高效地獲取數組中連續n個數的和。
應用 :序列中的元素可不斷地被修改,要快速地獲取某區間和(單點更新,區間求和)
前注 :如果每次要修改的不是單個元素,而是一個區間,那不應當用樹狀數組(效率過低)

操作:
1.修改元素(增減值) –> O(logn)
2.求區間和 –> O(logn)

實現:
給定序列(數列)A,我們設一個數組C滿足

C[i] = A[i–2^k+ 1] + … + A[i]
        (K爲 i在二進制下末尾0的個數, i >= 1)  --> 給定 i,則有 2^k = i&(i^(i-1)) = i&(-i)

圖示:
這裏寫圖片描述

修改元素:
————–>若要修改A[i]的值時,只需從C[i]往根節點一路上溯,調整這條路上的所有C[]。
區間求和:
————–>求數列的前n項和,只需找到n以前的所有最大子樹,把其根節點的C[]值加起來。(子樹的數目是n在二進制時1的個數)

int lowbit(int n)
{//求 2^k , k 爲n在二進制下末尾0的個數
    return n & (-n); // == n & (n^(n-1));
}
int Sum(int End)        
{//求前n項和
    int ans = 0;
    while(End > 0)
    {
        ans += treeC[End];
        End -= lowbit(End);
    }
    return ans;
}
void Plus(int pos,int num,int len) 
{//增加某元素的值
    while( pos <= len )
    {
        treeC[pos] += num;
        pos += lowbit(pos);
    }
}

例題 http://acm.hdu.edu.cn/showproblem.php?pid=1166


高級應用 : 區間更新 單點查找

操作:
1.區間更新
例如 :
在 區間[ Begin,End] 加 Add

則Plus(Begin,Add)   Plus(End+1,-Add)

實現了更新區間[ Begin,End] 的值而不改變其他值

2.單點查找

Sum(i) 即爲 A[i] 的值

例題 http://acm.hdu.edu.cn/showproblem.php?pid=1556


推廣 : 二維樹狀數組
用途 :
一個由數字構成的大矩陣,能進行
操作
1) 修改矩陣元素(增減值)
2) 求子矩陣的和

求和有
有 C[x][y] = sum{ A[i][j] , x - lowbit[x] +1 <=i <= x , y-lowbit[y]+1 <= j <=y }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章