Efficient Submatrix Sum Queries Using Prefix Sums

Problem Statement

Given an n×m integer matrix and q queries, each query specifies the coordinates of the top-left and bottom-right corners of a submatrix. For each query, compute the sum of all elements within the specified submatrix.

Solution Approach

The problem can be efficiently solved using 2D prefix sums. By precomputing the cumulative sum matrix, each query can be answered in constant time O(1).

The prefix sum array S is constructed such that S[i][j] represents the sum of all elements in the rectangle from (1,1) to (i,j). The sum of any submatrix with corners at (x1,y1) and (x2,y2) can then be computed using the inclusion-exclusion principle:

Submatrix Sum = S[x2][y2] - S[x1-1][y2] - S[x2][y1-1] + S[x1-1][y1-1]

Implementation Examples

C++ Solution

#include <iostream>
using namespace std;

const int MAX_SIZE = 1010;
int prefixSum[MAX_SIZE][MAX_SIZE];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    int rows, cols, queries;
    cin >> rows >> cols >> queries;
    
    // Build prefix sum matrix
    for (int i = 1; i <= rows; i++) {
        for (int j = 1; j <= cols; j++) {
            int value;
            cin >> value;
            prefixSum[i][j] = prefixSum[i-1][j] + prefixSum[i][j-1] 
                            - prefixSum[i-1][j-1] + value;
        }
    }
    
    // Process queries
    for (int i = 0; i < queries; i++) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        int result = prefixSum[x2][y2] - prefixSum[x1-1][y2] 
                   - prefixSum[x2][y1-1] + prefixSum[x1-1][y1-1];
        cout << result << "\n";
    }
    
    return 0;
}

Go Solution

package main

import (
    "fmt"
)

func main() {
    var rows, cols, queries int
    fmt.Scan(&rows, &cols, &queries)
    
    // Initialize prefix sum matrix
    prefixMatrix := make([][]int, rows+1)
    for i := range prefixMatrix {
        prefixMatrix[i] = make([]int, cols+1)
    }
    
    // Build prefix sums
    for i := 1; i <= rows; i++ {
        for j := 1; j <= cols; j++ {
            var val int
            fmt.Scan(&val)
            prefixMatrix[i][j] = prefixMatrix[i-1][j] + prefixMatrix[i][j-1] 
                               - prefixMatrix[i-1][j-1] + val
        }
    }
    
    // Handle queries
    for i := 0; i < queries; i++ {
        var x1, y1, x2, y2 int
        fmt.Scan(&x1, &y1, &x2, &y2)
        sum := prefixMatrix[x2][y2] - prefixMatrix[x1-1][y2] 
             - prefixMatrix[x2][y1-1] + prefixMatrix[x1-1][y1-1]
        fmt.Println(sum)
    }
}

Input/Output Example

Sample Input:

3 4 3
1 7 2 4
3 6 2 8
2 1 2 3
1 1 2 2
2 1 3 4
1 3 3 4

Sample Output:

17
27
21

Constraints

  • Matrix dimensions: 1 ≤ rows, cols ≤ 1000
  • Number of queries: 1 ≤ queries ≤ 200000
  • Coordinate bounds: 1 ≤ x1 ≤ x2 ≤ rows, 1 ≤ y1 ≤ y2 ≤ cols
  • Element values: -1000 ≤ matrix[i][j] ≤ 1000

Tags: algorithm prefix-sum matrix competitive-programming cpp

Posted on Sun, 28 Jun 2026 17:36:37 +0000 by trufla