完全認識樹狀數組


我搜遍了網絡,只在topcoder的網站上了解到樹狀數組這個結構是在設計壓縮算法時被發現的。這個數據結構真是天才的構想,膜拜!

樹狀數組的基礎是一個被構造出來的式子:C[i]=A[i]+A[i-1]+....+A[i-2^k+1];k代表i的二進制的最后連續0的個數 比如 對於1000和101000,k=3。至於這個式子是怎么被構造出來的,k為什么要代表這個。因為二進制的思想。

根據這個圖來看節點與其子樹的關系

接下來則很容易發現 節點和子節點的是有關系的,這種關系就是 i=j+lowbit(j); lowbit是j的最低位1所代表的數字 比如對於 1000(8的二進制) 1000=100+lowbit(100)=110+lowbit(110)=111+lowbit(111);

這個關系是樹狀數組的核心,有了這個關系,我們可以把子區間的變化以log2n的次數傳遞上去

那我們也知道了 當我們要求 1-n的和時,我們同樣把n表示為2進制,我們知道 C[i]=A[i]+A[i-1]+....+A[i-2^k+1]; 所以對於i 是不是我們只要把他所有的1都用上 就可以表示1-n的和?

舉個例子 求1-11000 則 Sum(11000)=C[11000]+C[10000]; 因為 根據C[i]的構造方法 C[i]是從A[i]開始的2^k個元素的和,則C[11000]求了A[11000] A[10111] A[10110] A[10101] A[10100] A[10010] A[10001] 這2^k個數 然后接着C[10000]求出了剩下 10000個元素的和 到了這我們就大概了解了樹狀數組的發明者的天才的構造是從何而來的了 普通的求1-n的和儲存的數據太多,而這位天才則想,我們能不能根據二進制的思想來儲存這些值呢?任何一個數,都可以由若干個二進制數相加而成,如果我們在求Sum(n)之前就知道了 n對應的二進制數從最低位開始,每個1所代表的數字的前2^i個數的和,我們不就能在時間復雜度log2(n)內求出所有的值 比如 101110 我們如果知道 101110->101101 101100->101001 101000->100001 100000->1各自的和,就可以在空間復雜度和時間復雜度很小的情況下求出1-101110了

然后對於區間和的修改 又利用每個小區間向上轉移 修改了大區間的和

總的來說 樹狀數組就是利用了二進制的思想求和 寫的有點亂 但只要你看懂了 二進制思想的那部分 相信看懂和實現樹狀數組並不難


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM