樹狀陣列與差分

2021-10-24 08:26:30 字數 2763 閱讀 3016

1.什麼是樹狀陣列?

顧名思義,就是用陣列來模擬樹形結構唄。那麼衍生出乙個問題,為什麼不直接建樹?答案是沒必要,因為樹狀陣列能處理的問題就沒必要建樹。和trie樹的構造方式有類似之處。

2.樹狀陣列可以解決什麼問題

可以解決大部分基於區間上的更新以及求和問題。

3.樹狀陣列和線段樹的區別在**

樹狀陣列可以解決的問題都可以用線段樹解決,這兩者的區別在**呢?樹狀陣列的係數要少很多,就比如字串模擬大數可以解決大數問題,也可以解決1+1的問題,但沒人會在1+1的問題上用大數模擬。

4.樹狀陣列的優點和缺點

修改和查詢的複雜度都是o(logn),而且相比線段樹係數要少很多,比傳統陣列要快,而且容易寫。

缺點是遇到複雜的區間問題還是不能解決,功能還是有限。『

樹狀陣列結構

黑色陣列代表原來的陣列(下面用a[i]代替),紅色結構代表我們的樹狀陣列(下面用c[i]代替),發現沒有,每個位置只有乙個方框,令每個位置存的就是子節點的值的和,則有

c[1] = a[1];

c[2] = a[1] + a[2];

c[3] = a[3];

c[4] = a[1] + a[2] + a[3] + a[4];

c[5] = a[5];

c[6] = a[5] + a[6];

c[7] = a[7];

c[8] = a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8];

可以發現,這顆樹是有規律的

c[i] = a[i - 2^k+1] + a[i - 2^k+2] + … + a[i]; //k為i的二進位制中從最低位到高位連續零的長度

例如i = 8(1000)時候,k = 3,可自行驗證。

這個怎麼實現求和呢,比如我們要找前7項和,那麼應該是sum = c[7] + c[6] + c[4];

而根據上面的式子,容易的出sumi = c[i] + c[i-2^k1] + c[(i - 2^k1) - 2^k2] + …;

2^k = x&(-x),此處是用的負數的儲存特性。

x&(-x)就是求x的二進位制從低到高最近乙個1的位置。例如8(1000),lowbit(8) = 4, 7(111),lowbit(7) = 1, 4(100), lowbit(4)=3。

其實樹狀陣列就是乙個二進位制上面的應用。

建立最基本的樹狀陣列

#include#include#include#includeusing namespace std;

int n;

int a[1005], c[1005];

int lowbit(int x)

int updata(int i, int k)

}int getsum(int i)

return res;

}int main()

for(int i = 0; i <= n; i++)

cout << endl;

for(int i = 0; i <= n; i++)

cout << endl;

return 0;

}

樹狀陣列與差分結合

求在某些個區間被加k,或者減k後某一點的值

1 int n,m;

2 int a[50005] = ,c[50005]; //對應原陣列和樹狀陣列

3 4 int lowbit(int x)

7 8 void updata(int i,int k)

13 }

14 15 int getsum(int i)

21 return res;

22 }

23 24 int main()

32

33 //[x,y]區間內加上k

34 updata(x,k); //a[x] - a[x-1]增加k

35 updata(y+1,-k); //a[y+1] - a[y]減少k

36

37 //查詢i位置的值

38 int sum = getsum(i);

39 40 return 0;

41 }

維護兩個數狀陣列,sum1[i] = d[i],sum2[i] = d[i]*(i-1);

int n,m;

int a[50005] = ;

int sum1[50005]; //(d[1] + d[2] + ... + d[n])

int sum2[50005]; //(1*d[1] + 2*d[2] + ... + n*d[n])

int lowbit(int x)

void updata(int i,int k)

}int getsum(int i)

return res;

}int main()

//[x,y]區間內加上k

updata(x,k); //a[x] - a[x-1]增加k

updata(y+1,-k); //a[y+1] - a[y]減少k

//求[x,y]區間和

int sum = getsum(y) - getsum(x-1);

return 0;

}

差分樹狀陣列

一 假設現在有乙個原陣列a 假設a 0 0 有乙個陣列d,d i a i a i 1 那麼 a i d 1 d 2 d i d陣列就是差分陣列 所以求a i 就可以用樹狀陣列維護d i 的字首和 即維護的是d i 的樹狀陣列 上面的數學思想可以實現區間修改,以及單點查詢。下附上 區間修改 1 n v...

差分 差分陣列 樹狀差分

原陣列 ai94 759差分陣列 bi9 5 3 24差分陣列的字首和94 759顯然通過求字首和可以做到單點查詢 他高效的地方在於區間修改,比如我們對區間 2,4 每個元素加上5,我們只需在差分陣列 b2 5,b5 5,然後求字首和即可 原陣列 ai94 759差分陣列 bi 903 2 1 差分...

差分詳解 樹狀陣列擴充套件

前言 現在還不是很懂,不過先把模板抄在這裡把。介紹一下差分,乙個很簡單的東西。一 簡介 已知陣列a為1,2,1,5,7,4 那麼差分陣列1,1,1,4,2,3 顯然,差分陣列就是當前項與前一項的差值。容易得到,an就是差分陣列的前n項和。二 那麼有什麼便利的地方呢?我們假想一下,現在要給1至4的區間...