演算法總結 樹狀陣列

2022-05-03 17:45:08 字數 2370 閱讀 2956

「樹狀陣列的題線段樹都能做。那我們為什麼要學習樹狀陣列,直接用線段樹搞不就好了。zz,既然用短小而精悍的樹狀陣列能搞,還用100多行的線段樹?」

以上為qbxt某位神牛一人飾兩角傾情演繹。

蒟蒻在臨近noip之時終於搞懂了樹狀陣列,在此做一下總結,算是鞏固?

類似線段樹,我們可以分三種模板

1、單點修改,區間求和

2、區間修改,單點查詢

3、區間修改,區間求和

樸素演算法是直接在陣列上更改,1的複雜度是o(n+m*l),2複雜度是o(n*l+m),3的複雜度是o(n*l+m*l)(n為修改次數,m為查詢次數,l為陣列長度),複雜度是非常高的,範圍稍微大一點就無法承受了,這時候就可以想到樹狀陣列了,樹狀陣列的複雜度是(m+n)*logl的,複雜度中的log是怎麼來的呢....

說到樹狀陣列,下面這個圖是必不可少的(圖是我盜的....)

這個c陣列就是樹狀陣列,觀察一下可以發現:

c[1]=a[1],

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

c[3]=a[3],

c[4]=a[1]+a[2]+a[3]+a[4]=c[2]+c[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陣列又a陣列的那幾個組成,把c陣列下標轉為二進位制:

1-->00000001

2-->00000010

3-->00000011

4-->00000100

5-->00000101

6-->00000110

7-->00000111

8-->00001000

假設c[i]中的i的二進位制中末尾0的個數為x(比如說:6,6的二進位制中末尾有1個0,x=1),c[i]=a[i]+a[i-1]+…+a[i-2^x+1](c[6]=a[6]+a[5]),這時我們就要用到乙個很重要的函式,lowbit(int x)用來求2^x,,這2^x個元素是從後往前遞減的

int lowbit(int

x)

修改單點的元素時,只需要把該元素到根節點的路徑上的c改變就行了,查詢時也只需要從該路徑上查詢,由於樹的深度最多為logl(可以看成二叉樹),那麼複雜度就會降下很多,這就是開頭我們提到的log**了

修改c[i]也要將i所在路徑上的c全部修改,也就是持續向上找father,i的父親節點為i+lowbit(i),

void add(int i,int

val)

}

求區間[a,b]的和,ans=sum(b)-sum(a-1),sum為從1到該點的a和

int sum(int

i)

return

s;}

第一種情況就是這樣了,第二三種情況區間修改我們可以利用查分的思想,其他的都差不多........吧

1

//1、單點修改,區間查詢

2 #include3 #include4 #include5

using

namespace

std;

6int c[500010];7

intn,m;

8int lowbit(intx)9

12void add(int i,int

val)

1320}21

int sum(int

i)22

29return

s;30}31

intmain()

3245

return0;

46 }

小仙女

1 #include2 #include3 #include4

using

namespace

std;

5int c[500010];6

intn,m;

7int lowbit(intx)8

11void add(int i,int

val)

1219}20

int sum(int

i)21

28return

s;29}30

intmain()

3140

for(int i=1;i<=m;i++)

4150

if(p==2)51

55}56return0;

57 }

老司機

樹狀陣列總結

樹狀陣列的基本知識已經被各種大牛和菜鳥講到爛了,我就不多說了,下面給出基本操作的 假定原陣列為a 1.n 樹狀陣列b 1.n 考慮靈活性的需要,使用int a傳陣列。define lowbit x x x int sum int a,int x void update int a,int x,int...

樹狀陣列總結

樹狀陣列是對乙個陣列改變某個元素和求和比較實用的資料結構。兩中操作都是o logn 在解題過程中,我們有時需要維護乙個陣列的字首和s i a 1 a 2 a i 但是不難發現,如果我們修改了任意乙個a i s i s i 1 s n 都會發生變化。可以說,每次修改a i 後,調整字首和s在最壞情況下...

樹狀陣列總結

今天學習了一下樹狀陣列,做乙個簡單總結。樹狀陣列可分為兩種操作,1 修改單個點,統計區間和 一般為 向上修改 update1 向下統計 sum1 2 修改區間,統計單個點 一般為向下修改 update2 向上統計 sum2 主要模板如下 int c n int lowbit int x 用於確定區間...