Prefix Sum of Matrix (Or 2D Array)
Given a 2D integer matrix mat[][]and a list of queries queries[][], the objective is to compute the sum of elements within a specific submatrix of the given matrix for each query.
Each query is defined by four integers [r1, c1, r2, c2].
- r1, c1: the top-left coordinate of the submatrix
- r2, c2: the bottom-right coordinate of the submatrix
All coordinates are inclusive, meaning the submatrix includes the elements at both (r1, c1) and (r2, c2).
Examples:
Input: mat[][] = [[1, 2, 3], queries[][] = [[0, 0, 1, 1], [1, 0, 2, 2]]
[1, 1, 0],
[4, 2, 2]]
Output: [5, 10]
Explanation:
Query 1 selects submatrix [[1, 2], [1, 1]] → sum = 5.
Query 2 selects submatrix [[1, 1, 0], [4, 2, 2]] → sum = 10.Input: mat[][] = [[1, 1, 1], queries[][] = [[1, 1, 2, 2], [0, 0, 2, 2], [0, 2, 2, 2]]
[1, 1, 1],
[1, 1, 1]]
Output: [4, 9, 3]
Explanation:
Query 1 selects submatrix [[1, 1], [1, 1]] → sum = 4.
Query 2 selects submatrix [[1, 1, 1], [1, 1, 1], [1, 1, 1]] → sum = 9.
Query 3 selects submatrix [[1], [1], [1]] → sum = 3.
Table of Content
[Naive Approach] Brute Force Summation - O(n × m × q) Time and O(1) Space
For each query, traverse the submatrix defined by its corners and accumulate the sum of all elements inside it.
This is done by nested loops over the specified row and column ranges.
#include <iostream>
#include <vector>
using namespace std;
vector<int> prefixSum2D(vector<vector<int>> &mat,
vector<vector<int>> &queries) {
vector<int> result;
// process each query to compute submatrix sum
for (auto &query : queries) {
int r1 = query[0], c1 = query[1];
int r2 = query[2], c2 = query[3];
int sum = 0;
// iterate through all elements inside the submatrix
for (int row = r1; row <= r2; row++) {
for (int col = c1; col <= c2; col++) {
sum += mat[row][col];
}
}
result.push_back(sum);
}
return result;
}
int main() {
vector<vector<int>> mat = {{1, 2, 3},
{1, 1, 0},
{4, 2, 2}};
vector<vector<int>> queries = {{0, 0, 1, 1,}, {1, 0, 2, 2}};
vector<int> result = prefixSum2D(mat, queries);
for(auto sum : result){
cout << sum << ' ';
}
cout << endl;
}
using namespace std;
vector<int> prefixSum2D(vector<vector<int>> &mat,
vector<vector<int>> &queries) {
vector<int> result;
// process each query to compute submatrix sum
for (auto &query : queries) {
int r1 = query[0], c1 = query[1];
int r2 = query[2], c2 = query[3];
int sum = 0;
// iterate through all elements inside the submatrix
for (int row = r1; row <= r2; row++) {
for (int col = c1; col <= c2; col++) {
sum += mat[row][col];
}
}
result.push_back(sum);
}
return result;
}
int main() {
vector<vector<int>> mat = {{1, 2, 3},
{1, 1, 0},
{4, 2, 2}};
vector<vector<int>> queries = {{0, 0, 1, 1,}, {1, 0, 2, 2}};
vector<int> result = prefixSum2D(mat, queries);
for(auto sum : result){
cout << sum << ' ';
}
cout << endl;
}
import java.util.ArrayList;
class GfG {
public static ArrayList<Integer> prefixSum2D(int[][] mat, int[][] queries) {
ArrayList<Integer> result = new ArrayList<>();
// process each query using inclusion-exclusion
for (int[] q : queries) {
int r1 = q[0], c1 = q[1], r2 = q[2], c2 = q[3];
int sum = 0;
// iterate through all elements inside the submatrix
for (int i = r1; i <= r2; i++) {
for (int j = c1; j <= c2; j++) {
sum += mat[i][j];
}
}
result.add(sum);
}
return result;
}
public static void main(String[] args) {
int[][] mat = {
{1, 2, 3},
{1, 1, 0},
{4, 2, 2}
};
int[][] queries = {
{0, 0, 1, 1},
{1, 0, 2, 2}
};
ArrayList<Integer> result = prefixSum2D(mat, queries);
for (int sum : result) {
System.out.print(sum + " ");
}
System.out.println();
}
}
def prefixSum2D(mat, queries):
result = []
# process each query using inclusion-exclusion
for q in queries:
r1, c1, r2, c2 = q
total = 0
# iterate through all elements inside the submatrix
for i in range(r1, r2 + 1):
for j in range(c1, c2 + 1):
total += mat[i][j]
result.append(total)
return result
if __name__ == "__main__":
mat = [
[1, 2, 3],
[1, 1, 0],
[4, 2, 2]
]
queries = [
[0, 0, 1, 1],
[1, 0, 2, 2]
]
result = prefixSum2D(mat, queries)
for sum in result:
print(sum, end=' ')
print()
using System;
using System.Collections.Generic;
class GfG {
public static List<int> prefixSum2D(int[][] mat, int[][] queries) {
List<int> result = new List<int>();
// process each query using inclusion-exclusion
foreach (var q in queries) {
int r1 = q[0], c1 = q[1], r2 = q[2], c2 = q[3];
int sum = 0;
// iterate through all elements inside the submatrix
for (int i = r1; i <= r2; i++) {
for (int j = c1; j <= c2; j++) {
sum += mat[i][j];
}
}
result.Add(sum);
}
return result;
}
public static void Main() {
int[][] mat = new int[][] {
new int[] {1, 2, 3},
new int[] {1, 1, 0},
new int[] {4, 2, 2}
};
int[][] queries = new int[][] {
new int[] {0, 0, 1, 1},
new int[] {1, 0, 2, 2}
};
List<int> result = prefixSum2D(mat, queries);
foreach (int sum in result) {
Console.Write(sum + " ");
}
Console.WriteLine();
}
}
function prefixSum2D(mat, queries) {
const result = [];
// process each query using inclusion-exclusion
for (let q of queries) {
let r1 = q[0], c1 = q[1], r2 = q[2], c2 = q[3];
let sum = 0;
// iterate through all elements inside the submatrix
for (let i = r1; i <= r2; i++) {
for (let j = c1; j <= c2; j++) {
sum += mat[i][j];
}
}
result.push(sum);
}
return result;
}
// Driver Code
const mat = [
[1, 2, 3],
[1, 1, 0],
[4, 2, 2]
];
const queries = [
[0, 0, 1, 1],
[1, 0, 2, 2]
];
const result = prefixSum2D(mat, queries);
for (let sum of result) {
process.stdout.write(sum + ' ');
}
console.log();
Output
5 10
[Approach] 2D Prefix Sum with Inclusion-Exclusion - O(n × m + q) Time and O(n × m) Space
The idea is to preprocess the matrix using a separate 2D prefix sum matrix pre[][] with 1-based indexing, where each cell stores the sum of the rectangle from the top-left corner to that cell. This allows us to compute the sum of any submatrix in constant time using the inclusion-exclusion principle.
For a query(r1, c1, r2, c2)
, the formula is: sum = total - top - left + overlaptotal => pre[r2][c2]
top => pre[r1-1][c2]
left => pre[r2][c1-1]
overlap => pre[r1][c1]
#include <iostream>
#include <vector>
using namespace std;
vector<int> prefixSum2D(vector<vector<int>> &mat, vector<vector<int>> &queries) {
int rows = mat.size(), cols = mat[0].size();
// create prefix matrix of size
// (rows+1)x(cols+1) to simplify boundaries
vector<vector<int>> pre(rows + 1, vector<int>(cols + 1, 0));
// Build prefix matrix with 1-based indexing
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
pre[i][j] = mat[i - 1][j - 1]
+ pre[i - 1][j]
+ pre[i][j - 1]
- pre[i - 1][j - 1];
}
}
vector<int> result;
// process each query using inclusion-exclusion
for (auto &q : queries) {
int topRow = q[0] + 1, leftCol = q[1] + 1;
int bottomRow = q[2] + 1, rightCol = q[3] + 1;
// get total area from (1,1) to (bottomRow, rightCol)
int total = pre[bottomRow][rightCol];
// subtract area above the submatrix
int top = pre[topRow - 1][rightCol];
// subtract area to the left of the submatrix
int left = pre[bottomRow][leftCol - 1];
// add back the overlapping top-left area,
// which was subtracted twice
int overlap = pre[topRow - 1][leftCol - 1];
// final submatrix sum using inclusion-exclusion
int sum = total - top - left + overlap;
result.push_back(sum);
}
return result;
}
int main() {
vector<vector<int>> mat = {
{1, 2, 3},
{1, 1, 0},
{4, 2, 2}
};
vector<vector<int>> queries = {
{0, 0, 1, 1},
{1, 0, 2, 2}
};
vector<int> result = prefixSum2D(mat, queries);
for (int sum : result) {
cout << sum << " ";
}
cout << endl;
}
using namespace std;
vector<int> prefixSum2D(vector<vector<int>> &mat, vector<vector<int>> &queries) {
int rows = mat.size(), cols = mat[0].size();
// create prefix matrix of size
// (rows+1)x(cols+1) to simplify boundaries
vector<vector<int>> pre(rows + 1, vector<int>(cols + 1, 0));
// Build prefix matrix with 1-based indexing
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
pre[i][j] = mat[i - 1][j - 1]
+ pre[i - 1][j]
+ pre[i][j - 1]
- pre[i - 1][j - 1];
}
}
vector<int> result;
// process each query using inclusion-exclusion
for (auto &q : queries) {
int topRow = q[0] + 1, leftCol = q[1] + 1;
int bottomRow = q[2] + 1, rightCol = q[3] + 1;
// get total area from (1,1) to (bottomRow, rightCol)
int total = pre[bottomRow][rightCol];
// subtract area above the submatrix
int top = pre[topRow - 1][rightCol];
// subtract area to the left of the submatrix
int left = pre[bottomRow][leftCol - 1];
// add back the overlapping top-left area,
// which was subtracted twice
int overlap = pre[topRow - 1][leftCol - 1];
// final submatrix sum using inclusion-exclusion
int sum = total - top - left + overlap;
result.push_back(sum);
}
return result;
}
int main() {
vector<vector<int>> mat = {
{1, 2, 3},
{1, 1, 0},
{4, 2, 2}
};
vector<vector<int>> queries = {
{0, 0, 1, 1},
{1, 0, 2, 2}
};
vector<int> result = prefixSum2D(mat, queries);
for (int sum : result) {
cout << sum << " ";
}
cout << endl;
}
import java.util.ArrayList;
public class GfG {
public static ArrayList<Integer> prefixSum2D(int[][] mat, int[][] queries) {
int rows = mat.length;
int cols = mat[0].length;
// create prefix matrix of size
// (rows+1)x(cols+1) to simplify boundaries
int[][] pre = new int[rows + 1][cols + 1];
// Build prefix matrix with 1-based indexing
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
pre[i][j] = mat[i - 1][j - 1]
+ pre[i - 1][j]
+ pre[i][j - 1]
- pre[i - 1][j - 1];
}
}
ArrayList<Integer> result = new ArrayList<>();
// process each query using inclusion-exclusion
for (int[] q : queries) {
int topRow = q[0] + 1;
int leftCol = q[1] + 1;
int bottomRow = q[2] + 1;
int rightCol = q[3] + 1;
// get total area from (1,1) to (bottomRow, rightCol)
int total = pre[bottomRow][rightCol];
// subtract area above the submatrix
int top = pre[topRow - 1][rightCol];
// subtract area to the left of the submatrix
int left = pre[bottomRow][leftCol - 1];
// add back the overlapping top-left area,
// which was subtracted twice
int overlap = pre[topRow - 1][leftCol - 1];
// final submatrix sum using inclusion-exclusion
result.add(total - top - left + overlap);
}
return result;
}
public static void main(String[] args) {
int[][] mat = {
{1, 2, 3},
{1, 1, 0},
{4, 2, 2}
};
int[][] queries = {
{0, 0, 1, 1},
{1, 0, 2, 2}
};
ArrayList<Integer> result = prefixSum2D(mat, queries);
for (int sum : result) {
System.out.print(sum + " ");
}
System.out.println();
}
}
def prefixSum2D(mat, queries):
rows = len(mat)
cols = len(mat[0])
# create prefix matrix of size (rows+1)x(cols+1) to simplify boundaries
pre = [[0] * (cols + 1) for _ in range(rows + 1)]
# Build prefix matrix with 1-based indexing
for i in range(1, rows + 1):
for j in range(1, cols + 1):
pre[i][j] = mat[i - 1][j - 1] \
+ pre[i - 1][j] \
+ pre[i][j - 1] \
- pre[i - 1][j - 1]
result = []
# process each query using inclusion-exclusion
for q in queries:
topRow = q[0] + 1
leftCol = q[1] + 1
bottomRow = q[2] + 1
rightCol = q[3] + 1
# get total area from (1,1) to (bottomRow, rightCol)
total = pre[bottomRow][rightCol]
# subtract area above the submatrix
top = pre[topRow - 1][rightCol]
# subtract area to the left of the submatrix
left = pre[bottomRow][leftCol - 1]
# add back the overlapping top-left area,
# which was subtracted twice
overlap = pre[topRow - 1][leftCol - 1]
# final submatrix sum using inclusion-exclusion
result.append(total - top - left + overlap)
return result
# Driver Code
if __name__ == "__main__":
mat = [
[1, 2, 3],
[1, 1, 0],
[4, 2, 2]
]
queries = [
[0, 0, 1, 1],
[1, 0, 2, 2]
]
result = prefixSum2D(mat, queries)
print(" ".join(map(str, result)))
using System;
using System.Collections.Generic;
class GfG {
public static List<int> prefixSum2D(int[][] mat, int[][] queries) {
int rows = mat.Length;
int cols = mat[0].Length;
// create prefix matrix of size (rows+1)x(cols+1) to simplify boundaries
int[,] pre = new int[rows + 1, cols + 1];
// Build prefix matrix with 1-based indexing
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
pre[i, j] = mat[i - 1][j - 1]
+ pre[i - 1, j]
+ pre[i, j - 1]
- pre[i - 1, j - 1];
}
}
List<int> result = new List<int>();
// process each query using inclusion-exclusion
foreach (int[] q in queries) {
int topRow = q[0] + 1;
int leftCol = q[1] + 1;
int bottomRow = q[2] + 1;
int rightCol = q[3] + 1;
// get total area from (1,1) to (bottomRow, rightCol)
int total = pre[bottomRow, rightCol];
// subtract area above the submatrix
int top = pre[topRow - 1, rightCol];
// subtract area to the left of the submatrix
int left = pre[bottomRow, leftCol - 1];
// add back the overlapping top-left area,
// which was subtracted twice
int overlap = pre[topRow - 1, leftCol - 1];
// final submatrix sum using inclusion-exclusion
result.Add(total - top - left + overlap);
}
return result;
}
public static void Main() {
int[][] mat = new int[][] {
new int[] {1, 2, 3},
new int[] {1, 1, 0},
new int[] {4, 2, 2}
};
int[][] queries = new int[][] {
new int[] {0, 0, 1, 1},
new int[] {1, 0, 2, 2}
};
List<int> result = prefixSum2D(mat, queries);
foreach (int sum in result) {
Console.Write(sum + " ");
}
Console.WriteLine();
}
}
function prefixSum2D(mat, queries) {
const rows = mat.length;
const cols = mat[0].length;
// create prefix matrix of size (rows+1)x(cols+1) to simplify boundaries
const pre = Array.from({ length: rows + 1 }, () =>
new Array(cols + 1).fill(0)
);
// Build prefix matrix with 1-based indexing
for (let i = 1; i <= rows; i++) {
for (let j = 1; j <= cols; j++) {
pre[i][j] = mat[i - 1][j - 1]
+ pre[i - 1][j]
+ pre[i][j - 1]
- pre[i - 1][j - 1];
}
}
const result = [];
// process each query using inclusion-exclusion
for (const q of queries) {
const topRow = q[0] + 1;
const leftCol = q[1] + 1;
const bottomRow = q[2] + 1;
const rightCol = q[3] + 1;
// get total area from (1,1) to (bottomRow, rightCol)
const total = pre[bottomRow][rightCol];
// subtract area above the submatrix
const top = pre[topRow - 1][rightCol];
// subtract area to the left of the submatrix
const left = pre[bottomRow][leftCol - 1];
// add back the overlapping top-left area,
// which was subtracted twice
const overlap = pre[topRow - 1][leftCol - 1];
// final submatrix sum using inclusion-exclusion
result.push(total - top - left + overlap);
}
return result;
}
// Driver Code
const mat = [
[1, 2, 3],
[1, 1, 0],
[4, 2, 2]
];
const queries = [
[0, 0, 1, 1],
[1, 0, 2, 2]
];
const result = prefixSum2D(mat, queries);
console.log(result.join(' '));
Output
5 10
[Efficient Approach] In-Place 2D Prefix Sum with Inclusion-Exclusion - O(n × m + q) Time and O(1) Space
This approach uses the 2D prefix sum technique to efficiently compute the sum of elements in any submatrix. The matrix is first preprocessed by calculating cumulative sums row-wise and then column-wise, so that each cell mat[i][j] holds the sum of the rectangle from the top-left (0,0) to (i, j).
For each query defined by (r1, c1) to (r2, c2), the submatrix sum is calculated in constant time using the inclusion-exclusion formula:
sum = mat[r2][c2] - mat[r2][c1 - 1] - mat[r1 - 1][c2] + mat[r1 - 1][c1 - 1]
#include <iostream>
#include <vector>
using namespace std;
vector<int> prefixSum2D(vector<vector<int>> &mat,
vector<vector<int>> &queries){
int rows = mat.size(), cols = mat[0].size();
// build prefix sum over rows
for (int i = 1; i < rows; i++) {
for (int j = 0; j < cols; j++) {
mat[i][j] += mat[i - 1][j];
}
}
// build prefix sum over columns
for (int j = 1; j < cols; j++) {
for (int i = 0; i < rows; i++) {
mat[i][j] += mat[i][j - 1];
}
}
vector<int> result;
// process each query using inclusion-exclusion
for (auto &q : queries) {
int r1 = q[0], c1 = q[1], r2 = q[2], c2 = q[3];
// get the total prefix sum from (0,0) to (r2,c2)
int total = mat[r2][c2];
// subtract the area above the submatrix (if any)
int left = (c1 > 0) ? mat[r2][c1 - 1] : 0;
// subtract the area to the left of the submatrix (if any)
int top = (r1 > 0) ? mat[r1 - 1][c2] : 0;
// add back the top-left overlapping area,
// which was subtracted twice
int overlap = (r1 > 0 && c1 > 0) ? mat[r1 - 1][c1 - 1] : 0;
// final submatrix sum using inclusion-exclusion
int sum = total - left - top + overlap;
result.push_back(sum);
}
return result;
}
int main() {
vector<vector<int>> mat = {{1, 2, 3},
{1, 1, 0},
{4, 2, 2}};
vector<vector<int>> queries = {{0, 0, 1, 1,}, {1, 0, 2, 2}};
vector<int> result = prefixSum2D(mat, queries);
for(auto sum : result){
cout << sum << ' ';
}
cout << endl;
}
using namespace std;
vector<int> prefixSum2D(vector<vector<int>> &mat,
vector<vector<int>> &queries){
int rows = mat.size(), cols = mat[0].size();
// build prefix sum over rows
for (int i = 1; i < rows; i++) {
for (int j = 0; j < cols; j++) {
mat[i][j] += mat[i - 1][j];
}
}
// build prefix sum over columns
for (int j = 1; j < cols; j++) {
for (int i = 0; i < rows; i++) {
mat[i][j] += mat[i][j - 1];
}
}
vector<int> result;
// process each query using inclusion-exclusion
for (auto &q : queries) {
int r1 = q[0], c1 = q[1], r2 = q[2], c2 = q[3];
// get the total prefix sum from (0,0) to (r2,c2)
int total = mat[r2][c2];
// subtract the area above the submatrix (if any)
int left = (c1 > 0) ? mat[r2][c1 - 1] : 0;
// subtract the area to the left of the submatrix (if any)
int top = (r1 > 0) ? mat[r1 - 1][c2] : 0;
// add back the top-left overlapping area,
// which was subtracted twice
int overlap = (r1 > 0 && c1 > 0) ? mat[r1 - 1][c1 - 1] : 0;
// final submatrix sum using inclusion-exclusion
int sum = total - left - top + overlap;
result.push_back(sum);
}
return result;
}
int main() {
vector<vector<int>> mat = {{1, 2, 3},
{1, 1, 0},
{4, 2, 2}};
vector<vector<int>> queries = {{0, 0, 1, 1,}, {1, 0, 2, 2}};
vector<int> result = prefixSum2D(mat, queries);
for(auto sum : result){
cout << sum << ' ';
}
cout << endl;
}
import java.util.*;
class GfG {
public static ArrayList<Integer> prefixSum2D(int[][] mat, int[][] queries) {
int rows = mat.length, cols = mat[0].length;
// build prefix sum over rows
for (int i = 1; i < rows; i++) {
for (int j = 0; j < cols; j++) {
mat[i][j] += mat[i - 1][j];
}
}
// build prefix sum over columns
for (int j = 1; j < cols; j++) {
for (int i = 0; i < rows; i++) {
mat[i][j] += mat[i][j - 1];
}
}
ArrayList<Integer> result = new ArrayList<>();
// process each query using inclusion-exclusion
for (int[] q : queries) {
int r1 = q[0], c1 = q[1], r2 = q[2], c2 = q[3];
// get the total prefix sum from (0,0) to (r2,c2)
int total = mat[r2][c2];
// subtract the area to the left of the submatrix (if any)
int left = (c1 > 0) ? mat[r2][c1 - 1] : 0;
// subtract the area above the submatrix (if any)
int top = (r1 > 0) ? mat[r1 - 1][c2] : 0;
// add back the top-left overlapping area,
// which was subtracted twice
int overlap = (r1 > 0 && c1 > 0) ? mat[r1 - 1][c1 - 1] : 0;
// final submatrix sum using inclusion-exclusion
int sum = total - left - top + overlap;
result.add(sum);
}
return result;
}
public static void main(String[] args) {
int[][] mat = {
{1, 2, 3},
{1, 1, 0},
{4, 2, 2}
};
int[][] queries = {
{0, 0, 1, 1},
{1, 0, 2, 2}
};
ArrayList<Integer> result = prefixSum2D(mat, queries);
for (int sum : result) {
System.out.print(sum + " ");
}
System.out.println();
}
}
def prefixSum2D(mat, queries):
rows, cols = len(mat), len(mat[0])
# build prefix sum over rows
for i in range(1, rows):
for j in range(cols):
mat[i][j] += mat[i - 1][j]
# build prefix sum over columns
for j in range(1, cols):
for i in range(rows):
mat[i][j] += mat[i][j - 1]
result = []
# process each query using inclusion-exclusion
for q in queries:
r1, c1, r2, c2 = q
# get the total prefix sum from (0,0) to (r2,c2)
total = mat[r2][c2]
# subtract the area to the left of the submatrix (if any)
left = mat[r2][c1 - 1] if c1 > 0 else 0
# subtract the area above the submatrix (if any)
top = mat[r1 - 1][c2] if r1 > 0 else 0
# add back the top-left overlapping area,
# which was subtracted twice
overlap = mat[r1 - 1][c1 - 1] if r1 > 0 and c1 > 0 else 0
# final submatrix sum using inclusion-exclusion
result.append(total - left - top + overlap)
return result
if __name__ == "__main__":
mat = [
[1, 2, 3],
[1, 1, 0],
[4, 2, 2]
]
queries = [
[0, 0, 1, 1],
[1, 0, 2, 2]
]
result = prefixSum2D(mat, queries)
for sum in result:
print(sum, end=' ')
print()
using System;
using System.Collections.Generic;
class GfG {
public static List<int> prefixSum2D(int[][] mat, int[][] queries) {
int rows = mat.Length, cols = mat[0].Length;
// build prefix sum over rows
for (int i = 1; i < rows; i++) {
for (int j = 0; j < cols; j++) {
mat[i][j] += mat[i - 1][j];
}
}
// build prefix sum over columns
for (int j = 1; j < cols; j++) {
for (int i = 0; i < rows; i++) {
mat[i][j] += mat[i][j - 1];
}
}
List<int> result = new List<int>();
// process each query using inclusion-exclusion
foreach (var q in queries) {
int r1 = q[0], c1 = q[1], r2 = q[2], c2 = q[3];
// get the total prefix sum from (0,0) to (r2,c2)
int total = mat[r2][c2];
// subtract the area to the left of the submatrix (if any)
int left = (c1 > 0) ? mat[r2][c1 - 1] : 0;
// subtract the area above the submatrix (if any)
int top = (r1 > 0) ? mat[r1 - 1][c2] : 0;
// add back the top-left overlapping area,
// which was subtracted twice
int overlap = (r1 > 0 && c1 > 0) ? mat[r1 - 1][c1 - 1] : 0;
// final submatrix sum using inclusion-exclusion
int sum = total - left - top + overlap;
result.Add(sum);
}
return result;
}
public static void Main() {
int[][] mat = new int[][] {
new int[] {1, 2, 3},
new int[] {1, 1, 0},
new int[] {4, 2, 2}
};
int[][] queries = new int[][] {
new int[] {0, 0, 1, 1},
new int[] {1, 0, 2, 2}
};
List<int> result = prefixSum2D(mat, queries);
foreach (int sum in result) {
Console.Write(sum + " ");
}
Console.WriteLine();
}
}
function prefixSum2D(mat, queries) {
const rows = mat.length, cols = mat[0].length;
// build prefix sum over rows
for (let i = 1; i < rows; i++) {
for (let j = 0; j < cols; j++) {
mat[i][j] += mat[i - 1][j];
}
}
// build prefix sum over columns
for (let j = 1; j < cols; j++) {
for (let i = 0; i < rows; i++) {
mat[i][j] += mat[i][j - 1];
}
}
const result = [];
// process each query using inclusion-exclusion
for (let q of queries) {
let r1 = q[0], c1 = q[1], r2 = q[2], c2 = q[3];
// get the total prefix sum from (0,0) to (r2,c2)
let total = mat[r2][c2];
// subtract the area to the left of the submatrix (if any)
let left = (c1 > 0) ? mat[r2][c1 - 1] : 0;
// subtract the area above the submatrix (if any)
let top = (r1 > 0) ? mat[r1 - 1][c2] : 0;
// add back the top-left overlapping area,
// which was subtracted twice
let overlap = (r1 > 0 && c1 > 0) ? mat[r1 - 1][c1 - 1] : 0;
// final submatrix sum using inclusion-exclusion
let sum = total - left - top + overlap;
result.push(sum);
}
return result;
}
// Driver Code
const mat = [
[1, 2, 3],
[1, 1, 0],
[4, 2, 2]
];
const queries = [
[0, 0, 1, 1],
[1, 0, 2, 2]
];
const result = prefixSum2D(mat, queries);
for (let sum of result) {
process.stdout.write(sum + ' ');
}
console.log();
Output
5 10