【數(shù)據(jù)結(jié)構(gòu)】樹狀數(shù)組

【數(shù)據(jù)結(jié)構(gòu)】樹狀數(shù)組

講到了線段樹,那就順便講講樹狀數(shù)組吧。

問題:

  • 一個(gè)固定大小 n 的有限數(shù)組 x
  • action 1 : 可以隨時(shí)更新某個(gè)節(jié)點(diǎn) i 的元素
  • action 2 : 可以查詢某個(gè)區(qū)間 [i, j] 內(nèi)所有元素的和

線段樹

假設(shè)一個(gè)長(zhǎng)度為 12 的線段樹,構(gòu)建結(jié)果如下:

構(gòu)建線段樹

在區(qū)間求和問題上,在葉子節(jié)點(diǎn),顯然劃線部分的值可以由父親節(jié)點(diǎn) - 左端葉子節(jié)點(diǎn)得到。

那么,這部分信息就是冗余的,沒有保存的必要。

對(duì)于區(qū)間求和問題,劃線部分是冗余的

同理,可以推導(dǎo)出所有冗余的部分如下:

同理,所有的冗余部分

那么,去除冗余部分后的結(jié)果如下:

去除冗余部分

給每一個(gè)節(jié)點(diǎn)一個(gè)編號(hào)。

我們假設(shè) i 為每個(gè)節(jié)點(diǎn)的編號(hào), L[i] 為該節(jié)點(diǎn)包含多少個(gè)元素的信息(就是區(qū)間內(nèi)的元素之和)。

可以得到如下表格。

序號(hào),元素個(gè)數(shù),二進(jìn)制表示

再來看看其二進(jìn)制表示:

每個(gè)節(jié)點(diǎn)序號(hào)和包含的元素個(gè)數(shù)

沒看出規(guī)律?

我們來分析一下:

節(jié)點(diǎn) 節(jié)點(diǎn)二進(jìn)制 父節(jié)點(diǎn) 父節(jié)點(diǎn)二進(jìn)制 節(jié)點(diǎn) -> 父節(jié)點(diǎn)
1 0001 2 0010 0001 + 0001 = 0010
2 0010 4 0100 0010 + 0010 = 0100
3 0011 4 0100 0011 + 0001 = 0100
4 0100 8 1000 0100 + 0100 = 1000
5 0101 6 0110 0101 + 0001 = 0110
6 0110 8 1000 0110 + 0010 = 1000

以上增加的值對(duì)應(yīng)表中的 L[i]。

從上可以看出當(dāng)前節(jié)點(diǎn) i 的父節(jié)點(diǎn)是 i+(i的“最低位1”),一般稱之為低位技術(shù):L[i] = i & (-i)

那么 i 節(jié)點(diǎn)的父節(jié)點(diǎn)的序號(hào)為:i + L[i]

同樣的規(guī)律,可以推算出 [1, i] 的值的第一個(gè)區(qū)間為 :i - L[i]

接下來上代碼:



    /* 
     * 假設(shè)樹狀數(shù)組為 T,長(zhǎng)度為 n,序號(hào) [1, ..., n]
     */
    
    // 低位技術(shù)
    #define LOWBIT(x)    ((x)&(-(x)))
    
    // 獲取區(qū)間 [1, x] 的和
    int getSum(int x) {
        int ret = 0;
        for (int i = x; i > 0; i-=LOWBIT(x)) {
            ret += T[i];
        }
        return ret;
    }
    
    // 獲取區(qū)間 [x, y] 的和
    int getSum(int x, int y) {
        return getSum(y) - getSum(x - 1);
    }
    
    // 更新第 x 點(diǎn)的值
    void updateOneNode(int x, int c) {
        for (int i = 0; i <= n; i+=LOWBIT(x)) {
            T[i] += c;
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、線段樹(區(qū)間樹)的概念 Segment Tree;線段樹屬于高級(jí)數(shù)據(jù)結(jié)構(gòu),經(jīng)常出現(xiàn)在算法競(jìng)賽中為什么要使用線段...
    哈哈大圣閱讀 1,412評(píng)論 0 1
  • 在已知了樹狀數(shù)組的使用方法,那么便可以用它來解決一些實(shí)際問題了,比如說下面一道經(jīng)典題:敵兵布陣 :HDU:1166...
    碧影江白閱讀 1,155評(píng)論 0 2
  • 自習(xí)的幾天觀察,基本能看出哪些同學(xué)比較勤奮。男生里最勤奮的還是我們寢室的幾位,住校外的顧偉也天天早早來自習(xí)。...
    劉子博家的臭老大閱讀 476評(píng)論 1 2
  • 1.25修子陽觀點(diǎn) 央行大動(dòng)作又來了!中行400億發(fā)行已獲批,銀行永續(xù)債春天漸行漸近。避險(xiǎn)需求疊加美元疲軟貴金屬投...
    修子陽閱讀 205評(píng)論 0 0
  • 獻(xiàn)給逆境的你!奏瑟鳴音吧,擊缶長(zhǎng)歌吧,那是成功後的你所再難體驗(yàn)的。 摘自 微博 設(shè)計(jì)目錄
    人間不系舟閱讀 151評(píng)論 0 0

友情鏈接更多精彩內(nèi)容