I don't have a scenario, but here goes the problem. This is one is just driving me crazy. There is a nxn boolean matrix initially all elements are 0, n <= 10^6 and given as input. Next there will be up to 10^5 queries. Each query can be either set all elements of column c to 0 or 1, or set all elements of row r to 0 or 1. There can be another type of query, printing the total number of 1's in column c or row r.
I have no idea how to solve this and any help would be appreciated. Obviously a O(n) solution per query is not feasible.
The idea of using a number to order the modifications is taken from Dukeling's post.
We will need 2 maps and 4 binary indexed tree (BIT, a.k.a. Fenwick Tree): 1 map and 2 BITs for rows, and 1 map and 2 BITs for columns. Let us call them
m_row
,f_row[0]
, andf_row[1]
;m_col
,f_col[0]
andf_col[1]
respectively.Map may be implemented with array, or tree like structure, or hashing. The 2 maps are used to store the last modification to a row/column. Since there can be at most 105 modification, you may use that fact to save space from simple array implementation.
BIT has 2 operations:
adjust(value, delta_freq)
, which adjusts the frequency of thevalue
bydelta_freq
amount.rsq(from_value, to_value)
, (rsq stands for range sum query) which finds the sum of the all the frequencies fromfrom_value
toto_value
inclusive.Let us declare global variable:
version
Let us define
numRow
to be the number of rows in the 2D boolean matrix, andnumCol
to be the number of columns in the 2D boolean matrix.The BITs should have size of at least MAX_QUERY + 1, since it is used to count the number of changes to the rows and columns, which can be as many as the number of queries.
Initialization:
Update algorithm:
Count algorithm:
The complexity is logarithmic in worst case for both update and count.
Take version just to mean a value that gets auto-incremented for each update.
Store the last version and last update value at each row and column.
Store a list of (versions and counts of zeros and counts of ones) for the rows. The same for the columns. So that's only 2 lists for the entire grid.
When a row is updated, we set its version to the current version and insert into the list for rows the version and
if (oldRowValue == 0) zeroCount = oldZeroCount else zeroCount = oldZeroCount + 1
(so it's not the number of zero's, rather the number of times a value was updated with a zero). Same for oneCount. Same for columns.If you do a print for a row, we get the row's version and last value, we do a binary search for that version in the column list (first value greater than). Then:
Not too sure whether the above will work.
That's O(1) for update, O(log k) for print, where k is the number of updates.