1. 程式人生 > >樹狀數組[數據結構]

樹狀數組[數據結構]

需要 結構 例子 img return 二進制 應該 date ash

樹狀數組

——!x^n+y^n=z^n

技術分享

  額,圖是網上搜來的...

  如圖:

我們令

c[1]=a[1]

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

c[3]=a[3]

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

c[5]=a[5]

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

c[7]=a[7]

c[8]=a[8]+c[4]+c[6]+c[7]

c[9]=a[9]

  其實我們是令c[n]的管轄範圍為i個元素,而這個i為n化為二進制時從後往前第一個出現1的地方及後面的0組成數的大小(記為lowbit(n))。

  舉個例子c[6]=a[5]+a[6]

6=(110)2

,lowbit(6)=(10)2=2;

  但這會產生一個問題,怎麽求lowbit?

  利用計算機補碼特性我們可以得到:

lowbit(x)=x&(-x)。[知道補碼的同學手推即可,不知道趕緊百度]

  當然作為數據結構要有他的用處。

  利用樹狀數組我們可以進行兩個比較簡單的操作:

<i>求a[1]+a[2]+L+a[x]的值

<ii>單點更新


<i>區間查詢

假設我們要求1~x的區間和,我們可以先查詢c[x],顯然c[x]是包含於我們要求的範圍裏的;

但當我們查詢完c[x]後,我們應該繼續查詢未查詢到的部分;

註意到:c[x]的管轄範圍:[x-lowbit(x)+1,x],故我們應繼續查詢c[x-lowbit(x)];

反復上面操作直至查詢完畢。

代碼:

1 int getsum(x){
2     int res=0;
3     for(;x;x-=lowbit(x))
4         res+=bit[x];
5     return res;
6 }

  本人樹狀數組一直喜歡打成bit啊...

<ii>單點更新

我們希望a[x]+inc

當然我們會先讓c[x]+inc;

然後我們需要找到管轄c[x]的c[y],因為x必須∈[y-lowbit(y)+1,y],我們怎麽做這件事?

其實我們只需要在x後面補上一個0就行了,想想是不是這樣。

代碼:

1 void update(x,inc){
2     for(;x<=n;x+=lowbit(x))
3         bit[x]+=inc;
4 }

  怎麽樣,是不是覺得代碼簡短很多?(對比線段樹)

樹狀數組[數據結構]