樹狀陣列 小白篇(1)

2022-07-14 09:21:12 字數 1885 閱讀 5888

身為一名弱省oier中的mengbier,簡單講一下我是怎麼學會基礎的樹狀陣列的

不算華麗的分割線

主要用於查詢任意一段資料中的所有元素之

經過簡單修改可以在log(n)的複雜度下進行範圍修改。

也就是說你通過一系列神奇的操作可以實現在乙個數列中,修改其中一項ax的值(還可以是一段),並求出前n項和(也可以是任意一段)。

額妹子!!!對不對?

我們知道 「樹狀陣列」 這個名詞的定語是 「樹狀」 ,它只是用來修飾陣列的對不對?

所以 「樹狀陣列」 就是一串有特異功能的陣列!

舉個例子:

正常的乙個陣列:a[1]=1, a[2]=2, a[3]=3, a[4]=4, a[5]=5, a[6]=6 ,a[7]=7, a[8]=8, a[9]=9

你要得到第n個數,就直接用a[n]來表示吧(廢話)

但你要算前x項和的話,就只能從a[1]一項一項加到a[x], 顯然當需要大量計算時,這種方法非常耗時!!!

於是機智的你想到了先計算出每乙個sn來,但是當需要修改怎麼辦?

難道要每乙個有關的sn都修改嗎?

於是大佬們yy出了樹狀陣列

神奇的陣列: c[1]=1, c[2]=3, c[3]=3, c[4]=10, c[5]=5, c[6]=11, c[7]=7, c[8]=36, c[9]=9

我說裡能表達所有資訊,你信不信?

神出鬼沒的分界線

設節點編號為x,那麼這個節點管轄的區間為2^k(其中k為x二進位制末尾0的個數)個元素。這個區間最後乙個元素為ax,

所以很明顯:cn = a(n – 2^k + 1) + ... + an

也就是說例如:  

c[1], 1的二進位制數為1,k=0,它就管長度為2^0的區間的和,暨c[1]=a[1]

c[2], 2的二進位制數為10,k=1,它就管長度為2^1的區間的和,暨c[2]=a[1]+a[2]

c[4], 4的二進位制數為100,k=2,它就管長度為2^2的區間的和,暨c[4]=a[1]+a[2]+a[3]+a[4]

c[6], 6的二進位制數為110,k=1,它就管長度為2^1的區間的和,暨c[6]=a[5]+a[6]

c[9], 9的二進位制數為1001,k=0,它就管長度為2^0的區間的和,暨c[9]=a[9]

強烈建議讀者用紙筆模擬一遍!!!

有乙個函式可以簡單的計算出這個2^k

1

int lowbit(intx)2

不信就用筆算一算

那我現在要求前n項和怎麼辦?

那就從c[n]開始,不重複的加完資料!

例如:我要求前6項和,那就從c[6]開始加,發現c[6]已經代表了2項,加完c[6],就加c[6-2],加c[4]的值,發現c[4]代表了4項,此時就加完前6項

還是看**吧

1

int sum(intn)2

910return

ans;

11 }

那要改一項的值就要改中每個有關的項

1

void add(int x,int v) //

x位置加v

28 }

那從a[x]+a[x+1]+a[x+2]+……+a[y-1]+a[y],就可以表示為sum(y)-sum(x-1);

就是任意連續數列和了

神出鬼沒的分界線

在下的文字功底還是不行,可能講的不是很好,請見諒

提供一些有關樹狀陣列的題目:

新手練習1

新手練習2(需要抽象化模型)

樹狀陣列 小白

樹狀陣列 bit 是一種利用樹的2進製特徵進行檢索的樹狀結構。樹狀結構是一種奇妙的資料結構,不僅非常高效,而且 十分簡潔 比線段樹的 要短且更易理解,但是可以解決的問題也是有限的,沒有線段樹那麼廣泛 樹狀陣列就是用來 動態的求字首和 的時間複雜度在log n之內 一般來說就是兩個操作 1.單點修改 ...

樹狀陣列 小白篇(2)暨區間修改

這篇主要來講一講樹狀陣列的區間修改 因為乙個乙個點改,毫無疑問耗時太長 所以,機智的人類yy出了用差分來表示陣列 為了便於理解,簡單一點陣列 a 1 0,a 2 0,a 3 0,a 4 0,a 5 0,a 6 0 a 7 0,a 8 0,a 9 0 用差分思想,delta x 表示a x a x 1...

樹狀陣列1 樹狀陣列入門

仔細看一下,發現tree的每乙個節點的高度並不是隨意的,而是由它轉成二進位制之後末尾連續零的數量決定的,連續零的數量加1,就是高度,例如 3 11 零的數量為0,加1等於1,所以它的高度就是1 6 110 零的數量為1,加1等於2,所以它的高度就是2 8 1000 零的數量為3,加1等於4,所以它的...