基本用法
例題與線段樹比較
樹狀陣列的基本操作流程與線段樹很像,故學習起來時是兩者的操作對比起來學的。線段樹學習之單點更新與區間更新
樹狀陣列(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...