範囲更新+バイナリインデックスツリーを使用した範囲クエリ


10

範囲のクエリと範囲の更新の両方を処理するためにバイナリインデックス付きツリー(fenwickツリー)をどのように変更できるかを理解しようとしています。

次のソースを見つけました:

http://kartikkukreja.wordpress.com/2013/12/02/range-updates-with-bit-fenwick-tree/ http://programmingcontests.quora.com/Tutorial-Range-Updates-in-Fenwick-Tree http ://apps.topcoder.com/forums/?module = Thread&threadID = 756271&start = 0&mc = 4#1579597

しかし、それらすべてを読んでも、2番目のバイナリインデックス付きツリーの目的や、それが何をするのか理解できませんでした。

誰かがバイナリインデックス付きツリーがこれらを処理するためにどのように変更されるかを私に説明してもらえますか?

回答:


9

空の配列があるとしましょう:

0  0  0  0  0  0  0  0  0  0  (array)
0  0  0  0  0  0  0  0  0  0  (cumulative sums)

そして、あなたは+5から[3..7]までの範囲の更新をしたいと思った:

0  0  0  5  5  5  5  5  0  0  (array)
0  0  0  5 10 15 20 25 25 25  (desired cumulative sums)

2つのバイナリインデックス付きツリーを使用して、目的の累積合計をどのように格納できますか?

トリックは、2つのバイナリインデックス付きツリー、BIT1とBIT2を使用することです。この場合、累積合計はそれらのコンテンツから計算されます。この例では、2つのツリーに次のものを格納します。

0   0   0   5   5   5   5   5   0   0  (BIT1)
0   0   0  10  10  10  10  10 -25 -25  (BIT2)

を見つけるsum[i]には、これを計算します。

sum[i] = BIT1[i] * i - BIT2[i]

例えば:

sum[2] = 0*2 - 0 = 0
sum[3] = 5*3 - 10 = 5
sum[4] = 5*4 - 10 = 10
...
sum[7] = 5*7 - 10 = 25
sum[8] = 0*8 - (-25) = 25
sum[9] = 0*9 - (-25) = 25

以前の範囲の更新で目的のBIT1およびBIT2の値を達成するために、3つの範囲の更新を行います。

  • BIT1のインデックス3..7に対して+5の範囲の更新を行う必要があります。

  • BIT2のインデックス3..7に対して+10の範囲の更新を行う必要があります。

  • BIT2のインデックス8..9に対して-25の範囲の更新を行う必要があります。

次に、もう1つ変換を行います。上記のBIT1とBIT2の値を保存する代わりに、実際にはそれらの累積合計を保存します。これにより、累積合計に4つの更新を行うことにより、上記の3つの範囲の更新を行うことができます。

BIT1sum[3] += 5
BIT1sum[8] -= 5
BIT2sum[3] += 10
BIT2sum[8] -= 35

一般に、値vをrange [i..j]に追加するアルゴリズムは次のようになります。

BIT1sum[i]   += v
BIT1sum[j+1] -= v
BIT2sum[i]   += v * (i-1)
BIT2sum[j+1] -= v * j

ここで、+ =および-=構文は、BIT累積合計データ構造をそのインデックスの正または負の値で更新することを意味します。インデックスでBIT累積合計を更新すると、そのインデックスの右側にあるすべてのインデックスに暗黙的に影響することに注意してください。例えば:

0 0 0 0 0 0 0 0 0 0 (original)

BITsum[3] += 5

0 0 0 5 5 5 5 5 5 5 (after updating [3])

BITsum[8] -= 5

0 0 0 5 5 5 5 5 0 0 (after updating [8])

フェンウィックツリーは、合計をバイナリツリーに格納します。上記の更新を時間でフェンウィックツリーに行うのは簡単です。O(logn)


BIT2を作成し、その後持った動機は何でしたsum[i] = BIT1[i] * i - BIT2[i]か?それは動作するようですが、それはとても恣意的です...これに来るのにどのような洞察が可能ですか?
1110101001 2014年

3
さて、私はこのアルゴリズムを発明しませんでした。私はあなたがしたようにそれを読みました。ただし、注意すべき点の1つは、範囲の更新を追加すると、累積合計が増加するシーケンス(5、10、15、20、...)になることです。BITはそのような増加するシーケンスを格納しません。ただし、定数(5)をBITに格納し、BIT値にインデックスを掛けると、希望どおりの増加するシーケンスが得られます。ただし、シーケンスの最初と最後を修正する必要があります。それが2番目のツリーの目的です。
JS1 2014年

私はあなたが実際に格納し、すなわち、反対のことをやっていると言うだろう-全体的に良いが、私はそれはあなたが「その代わりBIT1とBIT2について先に示された値を格納する、我々は実際に彼らの累積和を保存」を書いたことを混乱させるたデルタを
j_random_hacker
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.