AlgoMaster Logo

Increment Submatrices by One

mediumFrequencyUpdated September 21, 2026

Understanding the Problem

We start with an n x n grid of zeros. Each query gives us a rectangular region, and we need to add 1 to every cell inside that rectangle. After processing all queries, we return the final grid.

The direct interpretation is to loop through each rectangle and increment cells. The challenge is efficiency. With n up to 500, the matrix can have 250,000 cells, and with up to 10,000 queries, looping through every cell of every rectangle could touch up to 2.5 billion cells total. That is too slow.

This is a range update problem in two dimensions. In one dimension, range updates are solved efficiently with a difference array: mark the start and end of each update, then take a prefix sum. The same idea extends to 2D.

Key Constraints:

  • 1 <= queries.length <= 10^4 combined with 1 <= n <= 500 means a brute force of O(q n^2) reaches 2.5 10^9 operations, too slow within typical time limits. The approach has to make each query cheaper than scanning its full rectangle.
  • 0 <= row1i <= row2i < n and 0 <= col1i <= col2i < n means queries are always valid rectangles. There is no need to validate or clamp boundaries.

Approach 1: Brute Force

Intuition

Do exactly what the problem says. For each query, iterate over every cell in the specified rectangle and add 1 to it, using a nested loop per query.

This is correct but slow. Each query can touch up to n^2 cells, and there are up to q queries, so the worst case is O(q * n^2). It serves as a baseline before optimizing.

Algorithm

  1. Create an n x n matrix initialized to all zeros.
  2. For each query [row1, col1, row2, col2]:
    • For every row r from row1 to row2:
      • For every column c from col1 to col2:
        • Increment mat[r][c] by 1.
  3. Return the matrix.

Visualization and Code

Loading animation...

The cost comes from touching every cell inside each rectangle. In 1D, a difference array marks a range update with two operations instead of visiting every element. The next approach applies that idea to each affected row.

Approach 2: Row-wise 1D Difference Array

Intuition

Process the matrix one row at a time. A query [row1, col1, row2, col2] affects row r only when row1 <= r <= row2, and when it does, it increments columns col1 through col2 in that row.

Incrementing a contiguous range of columns in a single row is a 1D range update, which a difference array handles efficiently. Instead of incrementing every element from col1 to col2, add 1 at position col1 and subtract 1 at position col2 + 1. After processing all queries for a row, one prefix sum pass recovers the actual values.

For each query, iterate over the affected rows and mark the column-range update in each row's difference array. This costs O(number of affected rows) per query, up to O(n), instead of O(n^2).

Algorithm

  1. Create an n x n matrix mat initialized to zeros. Each row will serve as its own difference array.
  2. For each query [row1, col1, row2, col2]:
    • For every row r from row1 to row2:
      • Add 1 at mat[r][col1].
      • If col2 + 1 < n, subtract 1 at mat[r][col2 + 1].
  3. For each row, compute the prefix sum to convert the difference array into actual values.
  4. Return the matrix.

Visualization and Code

Loading animation...

This applies the difference array to columns but still loops over every affected row. The next approach extends the difference array to both dimensions, marking the entire rectangle with four operations regardless of its size and recovering all values with a single 2D prefix sum pass.

Approach 3: 2D Difference Array (Optimal)

Intuition

The 1D difference array extends to two dimensions. Instead of marking each row individually, mark the entire rectangular update with four corner operations on a 2D difference array.

To add 1 to every cell in the rectangle from (r1, c1) to (r2, c2), we update a difference matrix diff at four points:

  • diff[r1][c1] += 1 (start the increment here)
  • diff[r1][c2 + 1] -= 1 (cancel the increment past the right boundary)
  • diff[r2 + 1][c1] -= 1 (cancel the increment past the bottom boundary)
  • diff[r2 + 1][c2 + 1] += 1 (re-add because we subtracted twice at the bottom-right corner)

After marking all queries, we run a 2D prefix sum to recover the actual matrix values. Each query costs O(1) to mark, and the final prefix sum pass is O(n^2).

Algorithm

  1. Create an (n + 1) x (n + 1) difference array diff initialized to zeros (extra row and column to avoid boundary checks).
  2. For each query [row1, col1, row2, col2]:
    • diff[row1][col1] += 1
    • diff[row1][col2 + 1] -= 1
    • diff[row2 + 1][col1] -= 1
    • diff[row2 + 1][col2 + 1] += 1
  3. Compute the 2D prefix sum over diff:
    • First, do a row-wise prefix sum (left to right) for each row.
    • Then, do a column-wise prefix sum (top to bottom) for each column.
  4. Extract the top-left n x n portion as the result.

Visualization and Code

Loading animation...