Maximum sum submatrix

Last Updated : 30 Jun, 2026

Given a matrix mat[][] of size n × m and a query matrix queries[][] of size q × 2, where each query queries[i] = [a, b] represents the dimensions of a submatrix, find the maximum sum among all contiguous a × b submatrices for each query.

Examples:

Input: mat[][] = [[1, 2, 3, 9], [4, 5, 6, 2], [8, 3, 2, 6]], queries[][] = [[1, 1], [2, 2], [3, 3]]

blobid0_1781592716

Output: [9, 20, 38]
Explanation:
For 1 × 1, the maximum submatrix sum is 9.
For 2 × 2, the possible submatrix sums are 12, 16, 20, 20, 16, 16. The maximum is 20.
For 3 × 3, the possible submatrix sums are 34 and 38. The maximum is 38.
Therefore, the answer is [9, 20, 38].

Input: mat[][] = [[1, 2, 3, 9], [4, 5, 6, 2], [8, 3, 2, 6]], queries[][] = [[3,2]]
Output: [28]
Explanation: For a = 3 and b = 2, the possible 3 × 2 submatrices have sums 23, 21, and 28. The maximum is 28.

Try It Yourself
redirect icon

[Naive Approach] Check Every Possible Submatrix for Every Query - O(q × n × m × a × b) Time and O(1) Space

The idea is to process each query independently. For a query (a, b), generate every possible contiguous a × b submatrix in the matrix and calculate its sum by traversing all its elements. Among all possible submatrices, keep track of the maximum sum and store it as the answer for that query.

C++
#include <bits/stdc++.h>
using namespace std;

vector<int> maxSubMatSum(vector<vector<int>> &mat, vector<vector<int>> &queries)
{

    int n = mat.size();
    int m = mat[0].size();

    vector<int> res;

    // Process each query independently
    for (auto &qr : queries)
    {

        int a = qr[0];
        int b = qr[1];

        int mx = INT_MIN;

        // Try every possible a x b submatrix
        for (int row = 0; row + a <= n; row++)
        {
            for (int col = 0; col + b <= m; col++)
            {

                int currSum = 0;

                // Calculate current submatrix sum
                for (int i = row; i < row + a; i++)
                {
                    for (int j = col; j < col + b; j++)
                    {
                        currSum += mat[i][j];
                    }
                }

                mx = max(mx, currSum);
            }
        }

        res.push_back(mx);
    }

    return res;
}

int main()
{
    int n = 3, m = 4;

    vector<vector<int>> mat = {{1, 2, 3, 9}, {4, 5, 6, 2}, {8, 3, 2, 6}};

    int q = 3;

    vector<vector<int>> queries = {{1, 1}, {2, 2}, {3, 3}};

    vector<int> ans = maxSubMatSum(mat, queries);

    cout << "[";

    for (int i = 0; i < ans.size(); i++)
    {
        cout << ans[i];

        if (i != ans.size() - 1)
        {
            cout << ", ";
        }
    }

    cout << "]";

    return 0;
}
Java
import java.util.ArrayList;

class GFG {

    public static ArrayList<Integer>
    maxSubMatSum(int[][] mat, int[][] queries)
    {
        int n = mat.length;
        int m = mat[0].length;

        ArrayList<Integer> res = new ArrayList<>();

        // Process each query independently
        for (int[] qr : queries) {

            int a = qr[0];
            int b = qr[1];

            int mx = Integer.MIN_VALUE;

            // Try every possible a x b submatrix
            for (int row = 0; row + a <= n; row++) {
                for (int col = 0; col + b <= m; col++) {

                    int currSum = 0;

                    // Calculate current submatrix sum
                    for (int i = row; i < row + a; i++) {
                        for (int j = col; j < col + b;
                             j++) {
                            currSum += mat[i][j];
                        }
                    }

                    mx = Math.max(mx, currSum);
                }
            }

            res.add(mx);
        }

        return res;
    }

    public static void main(String[] args)
    {

        int n = 3, m = 4;

        int[][] mat = { { 1, 2, 3, 9 },
                        { 4, 5, 6, 2 },
                        { 8, 3, 2, 6 } };

        int q = 3;

        int[][] queries = { { 1, 1 }, { 2, 2 }, { 3, 3 } };

        ArrayList<Integer> ans = maxSubMatSum(mat, queries);

        System.out.print(ans);
    }
}
Python
def maxSubMatSum(mat, queries):
    n = len(mat)
    m = len(mat[0])

    res = []

    # Process each query independently
    for qr in queries:
        a = qr[0]
        b = qr[1]

        mx = float('-inf')

        # Try every possible a x b submatrix
        for row in range(n - a + 1):
            for col in range(m - b + 1):

                currSum = 0

                # Calculate current submatrix sum
                for i in range(row, row + a):
                    for j in range(col, col + b):
                        currSum += mat[i][j]

                mx = max(mx, currSum)

        res.append(mx)

    return res


if __name__ == '__main__':
    mat = [[1, 2, 3, 9], [4, 5, 6, 2], [8, 3, 2, 6]]

    queries = [[1, 1], [2, 2], [3, 3]]

    ans = maxSubMatSum(mat, queries)

    print('[', end='')

    for i in range(len(ans)):
        print(ans[i], end='' if i == len(ans) - 1 else ', ')

    print(']')
C#
using System;
using System.Collections.Generic;

class GFG {
    public List<int> maxSubMatSum(int[, ] mat,
                                  int[, ] queries)
    {
        int n = mat.GetLength(0);
        int m = mat.GetLength(1);
        int q = queries.GetLength(0);

        List<int> res = new List<int>();

        // Process each query independently
        for (int k = 0; k < q; k++) {
            int a = queries[k, 0];
            int b = queries[k, 1];

            int mx = int.MinValue;

            // Try every possible a x b submatrix
            for (int row = 0; row + a <= n; row++) {
                for (int col = 0; col + b <= m; col++) {
                    int currSum = 0;

                    // Calculate current submatrix sum
                    for (int i = row; i < row + a; i++) {
                        for (int j = col; j < col + b;
                             j++) {
                            currSum += mat[i, j];
                        }
                    }

                    mx = Math.Max(mx, currSum);
                }
            }

            res.Add(mx);
        }

        return res;
    }

    static void Main(string[] args)
    {
        int[, ] mat = { { 1, 2, 3, 9 },
                        { 4, 5, 6, 2 },
                        { 8, 3, 2, 6 } };

        int[, ] queries = { { 1, 1 }, { 2, 2 }, { 3, 3 } };

        GFG gfg = new GFG();
        List<int> ans = gfg.maxSubMatSum(mat, queries);

        Console.Write("[");

        for (int i = 0; i < ans.Count; i++) {
            Console.Write(ans[i]);

            if (i != ans.Count - 1) {
                Console.Write(", ");
            }
        }

        Console.WriteLine("]");
    }
}
JavaScript
function maxSubMatSum(mat, queries)
{
    const n = mat.length;
    const m = mat[0].length;

    const res = [];

    // Process each query independently
    for (const qr of queries) {
        const a = qr[0];
        const b = qr[1];

        let mx = Number.NEGATIVE_INFINITY;

        // Try every possible a x b submatrix
        for (let row = 0; row + a <= n; row++) {
            for (let col = 0; col + b <= m; col++) {

                let currSum = 0;

                // Calculate current submatrix sum
                for (let i = row; i < row + a; i++) {
                    for (let j = col; j < col + b; j++) {
                        currSum += mat[i][j];
                    }
                }

                mx = Math.max(mx, currSum);
            }
        }

        res.push(mx);
    }

    return res;
}

(function() {
const mat =
    [ [ 1, 2, 3, 9 ], [ 4, 5, 6, 2 ], [ 8, 3, 2, 6 ] ];

const queries = [ [ 1, 1 ], [ 2, 2 ], [ 3, 3 ] ];

const ans = maxSubMatSum(mat, queries);

console.log("[");

for (let i = 0; i < ans.length; i++) {
    console.log(ans[i]);

    if (i !== ans.length - 1) {
        console.log(", ");
    }
}

console.log("]");
})();

Output
[9, 20, 38]

[Expected Approach] Using 2D Prefix Sum - O(q * n * m) Time and O(n * m) Space

The idea is to first build a 2D prefix sum array that stores the cumulative sum of elements in the matrix. Using this prefix sum array, the sum of any a × b submatrix can be obtained directly. Then, for each query, traverse all possible a × b submatrices, find their sums using the prefix sum array, and maintain the maximum sum obtained.

Let us understand with example:
Input: n = 3, m = 4, mat[][] = [[1, 2, 3, 9], [4, 5, 6, 2], [8, 3, 2, 6]], q = 3, queries[][] = [[1, 1], [2, 2], [3, 3]]

  • For query (1, 1), every cell itself forms a submatrix. The maximum value in the matrix is 9.
  • For query (2, 2), the possible submatrix sums are 12, 16, 20, 20, 16, 16. Hence, the maximum sum is 20.
  • For query (3, 3), the two possible submatrix sums are 34 and 38. Hence, the maximum sum is 38.
  • Therefore, the final answer is [9, 20, 38].
C++
#include <bits/stdc++.h>
using namespace std;

// Returns the sum of submatrix [(r1, c1) ... (r2, c2)]
// using the 2D prefix sum array.
int getSum(vector<vector<int>> &pre, int r1, int c1, int r2, int c2)
{
    return pre[r2 + 1][c2 + 1] - pre[r1][c2 + 1] - pre[r2 + 1][c1] + pre[r1][c1];
}

vector<int> maxSubMatSum(vector<vector<int>> &mat, vector<vector<int>> &queries)
{
    int n = mat.size();
    int m = mat[0].size();
    int q = queries.size();

    // Build 2D prefix sum array.
    vector<vector<int>> pre(n + 1, vector<int>(m + 1, 0));

    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            pre[i][j] = mat[i - 1][j - 1] + pre[i - 1][j] + pre[i][j - 1] - pre[i - 1][j - 1];
        }
    }

    vector<int> res;
    res.reserve(q);

    // Process each query independently.
    for (auto &qr : queries)
    {
        int a = qr[0];
        int b = qr[1];

        int mx = INT_MIN;

        // Try every possible a x b submatrix.
        for (int i = 0; i + a <= n; i++)
        {
            for (int j = 0; j + b <= m; j++)
            {
                int sum = getSum(pre, i, j, i + a - 1, j + b - 1);
                mx = max(mx, sum);
            }
        }

        res.push_back(mx);
    }

    return res;
}

int main()
{
    int n = 3, m = 4;

    vector<vector<int>> mat = {{1, 2, 3, 9}, {4, 5, 6, 2}, {8, 3, 2, 6}};

    int q = 3;

    vector<vector<int>> queries = {{1, 1}, {2, 2}, {3, 3}};

    vector<int> ans = maxSubMatSum(mat, queries);

    cout << "[";

    for (int i = 0; i < ans.size(); i++)
    {
        cout << ans[i];

        if (i != ans.size() - 1)
        {
            cout << ", ";
        }
    }

    cout << "]";

    return 0;
}
Java
import java.util.ArrayList;
import java.util.List;

class GFG {

    // Returns the sum of submatrix [(r1, c1) ... (r2, c2)]
    // using the 2D prefix sum array.
    public static int getSum(int[][] pre, int r1, int c1,
                             int r2, int c2)
    {
        return pre[r2 + 1][c2 + 1] - pre[r1][c2 + 1]
            - pre[r2 + 1][c1] + pre[r1][c1];
    }

    public static List<Integer>
    maxSubMatSum(int[][] mat, int[][] queries)
    {
        int n = mat.length;
        int m = mat[0].length;
        int q = queries.length;

        // Build 2D prefix sum array.
        int[][] pre = new int[n + 1][m + 1];

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                pre[i][j] = mat[i - 1][j - 1]
                            + pre[i - 1][j] + pre[i][j - 1]
                            - pre[i - 1][j - 1];
            }
        }

        List<Integer> res = new ArrayList<>(q);

        // Process each query independently.
        for (int[] qr : queries) {
            int a = qr[0];
            int b = qr[1];

            int mx = Integer.MIN_VALUE;

            // Try every possible a x b submatrix.
            for (int i = 0; i + a <= n; i++) {
                for (int j = 0; j + b <= m; j++) {
                    int sum = getSum(pre, i, j, i + a - 1,
                                     j + b - 1);

                    mx = Math.max(mx, sum);
                }
            }

            res.add(mx);
        }

        return res;
    }

    public static void main(String[] args)
    {
        int n = 3, m = 4;

        int[][] mat = { { 1, 2, 3, 9 },
                        { 4, 5, 6, 2 },
                        { 8, 3, 2, 6 } };

        int q = 3;

        int[][] queries = { { 1, 1 }, { 2, 2 }, { 3, 3 } };

        List<Integer> ans = maxSubMatSum(mat, queries);

        System.out.print("[");

        for (int i = 0; i < ans.size(); i++) {
            System.out.print(ans.get(i));

            if (i != ans.size() - 1) {
                System.out.print(", ");
            }
        }

        System.out.print("]");
    }
}
Python
# Returns the sum of submatrix [(r1, c1) ... (r2, c2)]
# using the 2D prefix sum array.
def getSum(pre, r1, c1, r2, c2):
    return (pre[r2 + 1][c2 + 1]
            - pre[r1][c2 + 1]
            - pre[r2 + 1][c1]
            + pre[r1][c1])


def maxSubMatSum(mat, queries):
    n = len(mat)
    m = len(mat[0])
    q = len(queries)

    # Build 2D prefix sum array.
    pre = [[0] * (m + 1) for _ in range(n + 1)]

    for i in range(1, n + 1):
        for j in range(1, m + 1):
            pre[i][j] = (mat[i - 1][j - 1]
                         + pre[i - 1][j]
                         + pre[i][j - 1]
                         - pre[i - 1][j - 1])

    res = []

    # Process each query independently.
    for qr in queries:
        a, b = qr

        mx = float('-inf')

        # Try every possible a x b submatrix.
        for i in range(n - a + 1):
            for j in range(m - b + 1):

                sumVal = getSum(pre, i, j,
                                i + a - 1,
                                j + b - 1)

                mx = max(mx, sumVal)

        res.append(mx)

    return res


if __name__ == "__main__":
    n, m = 3, 4

    mat = [
        [1, 2, 3, 9],
        [4, 5, 6, 2],
        [8, 3, 2, 6]
    ]

    q = 3

    queries = [
        [1, 1],
        [2, 2],
        [3, 3]
    ]

    ans = maxSubMatSum(mat, queries)

    print(ans)
C#
using System;
using System.Collections.Generic;

class GFG {
    // Returns the sum of submatrix [(r1, c1) ... (r2, c2)]
    // using the 2D prefix sum array.
    static int getSum(int[, ] pre, int r1, int c1, int r2,
                      int c2)
    {
        return pre[r2 + 1, c2 + 1] - pre[r1, c2 + 1]
            - pre[r2 + 1, c1] + pre[r1, c1];
    }

    static List<int> maxSubMatSum(int[, ] mat,
                                  int[, ] queries)
    {
        int n = mat.GetLength(0);
        int m = mat.GetLength(1);
        int q = queries.GetLength(0);

        // Build 2D prefix sum array.
        int[, ] pre = new int[n + 1, m + 1];

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                pre[i, j] = mat[i - 1, j - 1]
                            + pre[i - 1, j] + pre[i, j - 1]
                            - pre[i - 1, j - 1];
            }
        }

        List<int> res = new List<int>();

        // Process each query independently.
        for (int k = 0; k < q; k++) {
            int a = queries[k, 0];
            int b = queries[k, 1];

            int mx = int.MinValue;

            // Try every possible a x b submatrix.
            for (int i = 0; i + a <= n; i++) {
                for (int j = 0; j + b <= m; j++) {
                    int sum = getSum(pre, i, j, i + a - 1,
                                     j + b - 1);
                    mx = Math.Max(mx, sum);
                }
            }

            res.Add(mx);
        }

        return res;
    }

    public static void Main()
    {
        int[, ] mat = { { 1, 2, 3, 9 },
                        { 4, 5, 6, 2 },
                        { 8, 3, 2, 6 } };

        int[, ] queries = { { 1, 1 }, { 2, 2 }, { 3, 3 } };

        List<int> ans = maxSubMatSum(mat, queries);

        Console.Write("[");

        for (int i = 0; i < ans.Count; i++) {
            Console.Write(ans[i]);

            if (i != ans.Count - 1) {
                Console.Write(", ");
            }
        }

        Console.WriteLine("]");
    }
}
JavaScript
function getSum(pre, r1, c1, r2, c2) {
    return pre[r2 + 1][c2 + 1] - pre[r1][c2 + 1] - pre[r2 + 1][c1] + pre[r1][c1];
}

function maxSubMatSum(mat, queries) {
    let n = mat.length;
    let m = mat[0].length;
    let q = queries.length;

    // Build 2D prefix sum array.
    let pre = Array.from({ length: n + 1 }, () => Array(m + 1).fill(0));

    for (let i = 1; i <= n; i++) {
        for (let j = 1; j <= m; j++) {
            pre[i][j] = mat[i - 1][j - 1] + pre[i - 1][j] + pre[i][j - 1] - pre[i - 1][j - 1];
        }
    }

    let res = [];

    // Process each query independently.
    for (let qr of queries) {
        let a = qr[0];
        let b = qr[1];

        let mx = -Infinity;

        // Try every possible a x b submatrix.
        for (let i = 0; i + a <= n; i++) {
            for (let j = 0; j + b <= m; j++) {
                let sum = getSum(pre, i, j, i + a - 1, j + b - 1);
                mx = Math.max(mx, sum);
            }
        }

        res.push(mx);
    }

    return res;
}

function main() {
    let n = 3, m = 4;

    let mat = [[1, 2, 3, 9], [4, 5, 6, 2], [8, 3, 2, 6]];

    let q = 3;

    let queries = [[1, 1], [2, 2], [3, 3]];

    let ans = maxSubMatSum(mat, queries);

    console.log('[');

    for (let i = 0; i < ans.length; i++) {
        console.log(ans[i]);

        if (i!= ans.length - 1) {
            console.log(', ');
        }
    }

    console.log(']');
}

main();

Output
[9, 20, 38]
Comment