樹狀陣列基礎

2021-09-28 19:43:04 字數 2539 閱讀 8380

基本用法

例題與線段樹比較

樹狀陣列的基本操作流程與線段樹很像,故學習起來時是兩者的操作對比起來學的。線段樹學習之單點更新與區間更新

樹狀陣列(binary indexed tree)是一種與線段樹類似的資料結構,又叫二進位制索引樹(spoil alert :跟二進位制有關),主要用於查詢區間和問題,每次只能修改乙個元素的值(加入多個輔助陣列後可實現區間修改和區間查詢)。

樹狀陣列的節點比線段樹少,但也能表示乙個陣列,c

cc陣列為每一列的頂端節點,c[i

]c[i]

c[i]

是子樹的葉子節點的權值之和。

若乙個陣列a

aa有8個數,那麼它的樹狀陣列c

cc如圖所示

由圖我們易看出,

c[

(0001)1

]= a[1]

c[(0010)2

]= a[1]

+ a[2]

c[(0011)3

]= a[3]

c[(0100)4

]= a[1]

+ a[2]

+ a[3]

+ a[4]

....

....

....

....

....

....

....

....

c[(1000)8

]= a[1]

+ a[2]

+ a[3]

+...

+ a[7]

+ a[8]

結合二進位制會發現,c[n]

=a[n-

2^k+1]

+...

+a[n]

由以上性質,我們引申出lowbit函式。

在算2

k2^k

2k時,我們可以使用快速冪的方法,但利用機器補碼算起來會更快。lowbit函式用於將乙個二進位制數所有高位1都去掉,只留下最低位的1,比如lowbit(3)=lowbit(0011(二進位制))=0001=1

int

lowbit

(int x)

若想對x

xx實現單點修改,則需要加上自己的lowbit,直到x≤n

x \leq n

x≤n,從而維護樹狀陣列。

//更新,單點修改 

void

update

(int x,

int k)

}

//單點查詢

intsearch

(int x)

}

void

add(

int x,

int k)

}

void

add(

int x,

int k)

}

//初始化樹狀陣列

void

inittree

(int num)

}

敵兵布陣

#include

#include

using

namespace std;

int n,m;

int tree[

2000010];

intlowbit

(int x)

//區間查詢

intsum

(int x)

return ans;

}//區間修改

void

add(

int x,

int k)

}//初始化樹狀陣列

void

inittree

(int num)

}int

main()

int x,y;

scanf

("%d%d"

,&x,

&y);

if(str[0]

=='q')if

(str[0]

=='s')if

(str[0]

=='a')}

}return0;

}

樹狀陣列可以高效的進行區間統計,思想類似於線段樹,但是比線段樹節省空間(開兩倍的原陣列就ok,線段樹4倍),**複雜度比線段樹低,實際查詢時間也比線段樹快(樹狀陣列最壞log

(n)log(n)

log(n)

,線段樹nlo

g(n)

nlog(n)

nlog(n

).但是!樹狀陣列的適用範圍比線段樹小。

這週只寫了一題,下週會努力把其他的也補起來的orz

基礎樹狀陣列

la 4329 2008年北京區域賽 題目分析 首先是乘法原理加法原理計數,對a i 當做裁判的情況,記c i d i 分別表示前面和後面小於它的數的個數,ai當裁判方法數就是 c i n i 1 d i d i i c i 了 具體的見 演算法競賽入門經典訓練指南 197頁 樹狀陣列見194 19...

樹狀陣列基礎

樹狀陣列,又稱二進位制索引樹,英文名binary indexed tree。樹狀陣列用來求區間元素和,求一次區間元素和的時間效率為o logn 有些同學會覺得很奇怪。用乙個陣列s i 儲存序列a的前i個元素和,那麼求區間i,j的元素和不就為s j s i 1 那麼時間效率為o 1 豈不是更快?但是,...

樹狀陣列基礎

關於樹狀陣列的講解推薦 演算法競賽入門經典訓練指南 一維版本 洛谷3374 分析 樹狀陣列裸的模板題 1 include2 include3 include4 using namespace std 5const int maxn 500000 10 6 intc maxn 7int n,m 8in...