• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            雁過無痕

              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::

            樹狀數組(Fenwick tree,又名binary indexed tree),是一種很實用的數據結構。它通過用節點i,記錄數組下標在[ i –2^k + 1, i]這段區間的所有數的信息(其中,ki的二進制表示中末尾0的個數,設lowbit(i) = 2^k),實現在O(lg n) 時間內對數組數據的查找和更新。

            樹狀數組的傳統解釋圖,不能很直觀的看出其所能進行的更新和查詢操作。其最主要的操作函數lowbit(k)與數的二進制表示相關,本質上仍是一種二分。因而可以通過二叉樹,對其進行分析。事實上,從二叉樹圖,我們對它所能進行的操作和不能進行的操作一目了然。

            和前面提到的點樹類似,先畫一棵二叉樹,然后對節點中序遍歷(點樹是采用廣度優先),每個節點仍然只記錄左子樹信息,見圖:

             

             

            由于采用的是中序遍歷,從節點1到節點k時,剛好有k個葉子被統計。

            可以證明:

              葉子k,一定在節點k子樹下。

              以節點k為根的樹,其子樹共有葉子lowbit(k)

            節點k的父節點是:k + lowbit(k) k - lowbit(k) 

            節點k + lowbit(k) 是節點k的最近父節點,且節點k在它的子樹下。

            節點k - lowbit(k) 是節點k的最近父節點,且節點k在它的子樹下。

            節點k,統計的葉子范圍為:(k - lowbit(k),  k]

            節點k的左孩子是:k - lowbit(k) / 2

             

            下面分析樹狀數組兩面主要應用:

            1 更新數據x,進行區間查詢。

            2 更新區間,查詢某個數。

            由于,樹狀數組只統計了左子樹的信息,因而只能查詢更新區間[1, x]。只在在滿足[x,y]的信息可以由[1,x-1][1,y]的信息推導出時,才能進行區間[x,y]的查詢更新。這也是樹狀數組不能用于任意區間求最值的根本原因。

             

            先定義兩個集合:

            up_right(k) 節點k所有的父節點,且節點k在它們的子樹下。

            up_left(k)   節點k所有的父節點,且節點k在它們的子樹下。

             

            1  更新數據x,查詢區間[1,y]

            顯然,更新葉子x,要找出葉子x在哪些節點的子樹下。因而節點k、所有的up_right(k)

            都要更新。

            查詢[1, y],實際上就是把該區間拆分成一系列小區間,并找出統計這些區間的節點。可以通過找出y在哪些節點的子樹下,這些節點恰好不重復的統計了區間[1, y-1]。因而要訪問節點y、所有的up_left(y)

             

            2 更新區間[1,y],查詢數據x

              這和前面的操作恰好相反。與前面的最大不同之處在于:節點保存的不再是其葉子總個數這些信息,而是該區間的所有葉子都改變了多少。也就是說:每個葉子的信息,分散到了所有對它統計的節點上。因此操作和前面相似:

              更新[1,y]時,更新節點y、所有up_left(y)

              查詢x時,  訪問x、所有up_right(x)

             

            前面的樹狀數組,只對左子樹信息進行統計,如果從后往前讀數據初始化樹狀數組,則變成只對右子樹信息進行統計,這時更新和查詢操作,剛好和前面的相反。

             

            一般情況下,樹狀數組比點樹省空間,對區間[1, M]只要M+1空間,查詢更新時定位節點比較快,定位父節點和左右孩子相對麻煩點(不過,一般也不用到。從上往下查找,可參考下面代碼中的erease_nth函數(刪除第n小的數))。

             

            下面是使用樹狀數組的實現代碼(求逆序數和模擬約瑟夫環問題):


            樹狀數組





            作者: flyinghearts
            出處: http://www.cnblogs.com/flyinghearts/
            本文采用知識共享署名-非商業性使用-相同方式共享 2.5 中國大陸許可協議進行許可,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。


            posted on 2011-04-11 23:54 flyinghearts 閱讀(1923) 評論(0)  編輯 收藏 引用 所屬分類: 算法
            久久久久久久综合日本| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 精品久久久久久无码人妻热| 久久九色综合九色99伊人| 亚洲国产成人久久笫一页| 婷婷综合久久中文字幕蜜桃三电影| 久久精品国产亚洲AV电影| 一本久久久久久久| 亚洲v国产v天堂a无码久久| 久久91亚洲人成电影网站| 97超级碰碰碰碰久久久久| 亚洲国产成人久久笫一页| 亚洲国产另类久久久精品小说 | 国产精品伊人久久伊人电影 | 国产激情久久久久影院| 久久免费视频观看| 色综合久久88色综合天天| 99国内精品久久久久久久| 91精品久久久久久无码| 久久99国产精品成人欧美| 久久久久97国产精华液好用吗| 久久久青草青青国产亚洲免观| 深夜久久AAAAA级毛片免费看| 久久精品国产亚洲av麻豆图片| 久久精品国产99久久久古代| 99久久99久久久精品齐齐 | 精品久久久久久中文字幕人妻最新| 日产精品久久久久久久性色| 国产精品一久久香蕉国产线看观看 | 色天使久久综合网天天| 国产精品综合久久第一页 | 伊人久久大香线蕉AV一区二区| 亚洲人成网站999久久久综合 | 狠色狠色狠狠色综合久久| 久久精品国产72国产精福利| 久久国产V一级毛多内射| 久久久久久久综合狠狠综合| 久久人人爽人人爽人人片av高请 | 999久久久无码国产精品| 久久亚洲中文字幕精品一区| 国产精品无码久久久久久|