Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The idea of using a number to order the modifications is taken from Dukeling's post.</p> <p>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 <code>m_row</code>, <code>f_row[0]</code>, and <code>f_row[1]</code>; <code>m_col</code>, <code>f_col[0]</code> and <code>f_col[1]</code> respectively.</p> <p>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 10<sup>5</sup> modification, you may use that fact to save space from simple array implementation.</p> <p>BIT has 2 operations:</p> <ul> <li><code>adjust(value, delta_freq)</code>, which adjusts the frequency of the <code>value</code> by <code>delta_freq</code> amount.</li> <li><code>rsq(from_value, to_value)</code>, (rsq stands for range sum query) which finds the sum of the all the frequencies from <code>from_value</code> to <code>to_value</code> inclusive.</li> </ul> <p>Let us declare global variable: <code>version</code></p> <p>Let us define <code>numRow</code> to be the number of rows in the 2D boolean matrix, and <code>numCol</code> to be the number of columns in the 2D boolean matrix.</p> <p>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.</p> <p>Initialization:</p> <pre><code>version = 1 # Map should return &lt;0, 0&gt; 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 </code></pre> <p>Update algorithm:</p> <pre><code>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 &lt;prevValue, prevVersion&gt; = m_row.get(idx) if ( prevVersion &gt; 0 ): f_row[prevValue].adjust( prevVersion, -1 ) m_row.map( idx, &lt;value, version&gt; ) f_row[value].adjust( version, 1 ) else: &lt;prevValue, prevVersion&gt; = m_col.get(idx) if ( prevVersion &gt; 0 ): f_col[prevValue].adjust( prevVersion, -1 ) m_col.map( idx, &lt;value, version&gt; ) f_col[value].adjust( version, 1 ) version = version + 1 </code></pre> <p>Count algorithm:</p> <pre><code>count(isRow, idx): if (isRow): # If this is row, we want to find number of reverse modifications # done by updating the columns &lt;value, row_version&gt; = 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 &lt;value, col_version&gt; = 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 </code></pre> <p>The complexity is logarithmic in worst case for both update and count.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload