番号を使用して変更を注文するというアイデアは、Dukelingの投稿から引用されています。
2つのマップと4つのバイナリインデックスツリー(BIT、別名フェニックツリー)が必要になります。行には1つのマップと2つのBIT、列には1つのマップと2つのBITが必要です。m_row
それらを、、、f_row[0]
およびf_row[1]
;と呼びましょう。m_col
、f_col[0]
およびf_col[1]
それぞれ。
マップは、配列、ツリーのような構造、またはハッシュを使用して実装できます。2つのマップは、行/列への最後の変更を格納するために使用されます。最大で105の変更が可能であるため、その事実を使用して、単純な配列の実装からスペースを節約できます。
BITには2つの操作があります。
adjust(value, delta_freq)
value
、量によって頻度を調整しますdelta_freq
。
rsq(from_value, to_value)
、(rsqは範囲合計クエリを表します)は、からfrom_value
までのすべての頻度の合計を求めto_value
ます。
グローバル変数を宣言しましょう:version
numRow
2Dブール行列の行数と2Dブール行列の列数を定義しましょうnumCol
。
BITは、行と列への変更の数をカウントするために使用されるため、少なくともMAX_QUERY + 1のサイズである必要があります。これは、クエリの数と同じ数になる可能性があります。
初期化:
version = 1
# Map should return <0, 0> for rows or cols not yet
# directly updated by query
m_row = m_col = empty map
f_row[0] = f_row[1] = f_col[0] = f_col[1] = empty BIT
アルゴリズムの更新:
update(isRow, value, idx):
if (isRow):
# Since setting a row/column to a new value will reset
# everything done to it, we need to erase earlier
# modification to it.
# For example, turn on/off on a row a few times, then
# query some column
<prevValue, prevVersion> = m_row.get(idx)
if ( prevVersion > 0 ):
f_row[prevValue].adjust( prevVersion, -1 )
m_row.map( idx, <value, version> )
f_row[value].adjust( version, 1 )
else:
<prevValue, prevVersion> = m_col.get(idx)
if ( prevVersion > 0 ):
f_col[prevValue].adjust( prevVersion, -1 )
m_col.map( idx, <value, version> )
f_col[value].adjust( version, 1 )
version = version + 1
カウントアルゴリズム:
count(isRow, idx):
if (isRow):
# If this is row, we want to find number of reverse modifications
# done by updating the columns
<value, row_version> = m_row.get(idx)
count = f_col[1 - value].rsq(row_version + 1, version)
else:
# If this is column, we want to find number of reverse modifications
# done by updating the rows
<value, col_version> = m_col.get(idx)
count = f_row[1 - value].rsq(col_version + 1, version)
if (isRow):
if (value == 1):
return numRow - count
else:
return count
else:
if (value == 1):
return numCol - count
else:
return count
複雑さは、更新とカウントの両方で最悪の場合は対数です。