Binary Indexed Tree(BIT)
概要
- 要素の更新がありうる数列について、区間和の計算が高速にできる
- 同様に更新ありの任意区間の区間和を高速に計算可能なSegment Treeと比較して空間計算量が半分程度
- ただしSegment Treeのように最小値などの計算に使うといったような応用力はない
- Segment Treeの各nodeが表現している区間を 、そのnodeの演算結果(表現区間の区間和)を としたときに、 であるような区間のうち要素数が最大の区間の演算結果だけをBITで保持するようにする
i.e. - ある部分和 を取得したいときは区間を適切に分割するとBITに対応する値を持っているので、それらの和をとる
- 具体的には のように を更新していき、 になるまで更新したときに出てくる値を使う( はbit論理積演算)
e.g.
- 具体的には のように を更新していき、 になるまで更新したときに出てくる値を使う( はbit論理積演算)
- 任意の区間和 を求めるときは で計算できる
- とする
- 更新時は値の変更が影響を受けるノードだけ更新する
- 具体的には全区間を としたとき、 のように を更新していき、 になるまで更新したときに出てくる値を更新する
e.g. のBITで要素 を更新したとき、 を更新する
- 具体的には全区間を としたとき、 のように を更新していき、 になるまで更新したときに出てくる値を更新する
- 上記計算の関係から数列は1-originで考えることになる
- 計算時間は要素の更新に 、結果の取得に
BITを用いた代表的な計算として、 を昇順にバブルソートしたときに要素の交換が行われる、つまり かつ であるような の組の数(転倒数)を求めるというものがある。
- とする
- とする
- を昇順に安定ソートした順に、以下の操作を実行する
- を に加算する
- BITで表現している数列の 番目に を加算するような更新をする
- を出力する
実装
- 簡単のため数列の各要素は整数とする
- 数列の 番目の要素までの部分和を返す関数
Get(i)
をもつ - 数列の 番目の要素を に更新する関数
Update(i, v)
をもつ - 任意の区間 ] の区間和を返す関数
Query(l, r)
をもつ Inversion(A)
で数列 の転倒数を求める
Python3で実装する
Powered by OnlineGDB
Goで実装する
Python3ではソートを1行で書けるところをGoでは準備に数行必要なこと以外は実装量に大きな差はない