The idea of ββusing a number to order modifications is taken from the post Dukeling.
We will need 2 maps and 4 binary indexed trees (BIT, aka Fenwick Tree): 1 map and 2 BIT for rows, 1 map and 2 BIT for columns. Call them m_row , f_row[0] and f_row[1] ; m_col , f_col[0] and f_col[1] respectively.
A map can be implemented using an array or tree structure or hash. 2 cards are used to store the latest row / column modification. Since the modification can be no more than 10 5, you can use this fact to save space from a simple array implementation.
BIT has 2 operations:
adjust(value, delta_freq) , which adjusts the frequency of value to delta_freq .rsq(from_value, to_value) , (rsq means requesting the sum of the range), which finds the sum of all frequencies from from_value to to_value inclusive.
Declare a global variable: version
We define numRow as the number of rows in a two-dimensional Boolean matrix, and numCol is the number of columns in a two-dimensional Boolean matrix.
BITs must have a size of at least MAX_QUERY + 1, as it is used to count the number of changes in rows and columns that can be equal to the number of queries.
Initialization:
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 algorithm:
update(isRow, value, idx): if (isRow):
Counting Schedule:
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
The worst case logarithmic complexity for updating and counting.