GFG App
Open App
Browser
Continue

# Find the sum of diagonals passing through given coordinates for Q query

Given a 2D matrix of size N x M and Q queries where each query represents a coordinate (x, y) of the matrix, the task is to find the sum of all elements lying in the diagonals that pass through the given point.

Examples:

Input: N = 4, M = 4, mat[][] = {{1, 2, 2, 1}, {2, 4, 2, 4}, {2, 2, 3, 1}, {2, 4, 2, 4}}, query = { {0, 0}, {3, 1}, {3, 3} }
Output:  12, 13, 12
Explanation:
For query 1, The sum of all diagonal elements from (0, 0) is 1 + 4 + 3 + 4 = 12
For query 2, The sum of all diagonal elements from (3, 1) is 2 + 4 + 3 + 4 = 13
For query 3, The sum of all diagonal elements from (3, 3) is 4 + 3 + 4 + 1 = 12

Input: N = 3, M = 4, mat[][] = {{1, 0, 1}, {0, 1, 1}, {1, 1, 0}}, query = {{1, 1}, {2, 1}}
Output: 4, 2

Naive approach: The simple way to solve the problem is as follows:

• For each query run a loop to calculate the sum of the left inclined diagonal that passes through (x, y).
• Run another loop to calculate the sum of the right inclined diagonal that passes (x, y).
• In the calculation of these two side diagonals, we counted (x, y) twice. So now subtract that from the summation of both diagonal sums.

Time Complexity: O(Q * N * M)
Auxiliary Space: O(1)

Efficient Approach: The problem can be solved efficiently based on the following idea:

Pre-compute the left inclined and right inclined diagonal sums and store it in such a way that can be easily accessed and utilized for all values of (x, y)

In any matrix of size N x M, the total number of left inclined diagonal or right inclined diagonal is always N + M – 1. So create two vectors of size (N + M – 1) to store the sum of every that particular type of diagonal in the respective vector.

The value of (i+j) along right inclined diagonals are equals and (N-i+j-1) along left inclined diagonals are equal. So these values can be used as the indices for storing the sum of that diagonal.

Illustrations:

In this 3 x 4 matrix:

1     2     3     4
________________

1  | A00  A01  A02  A03

2  | A10  A11  A12  A13

3  | A20  A21  A22  A23

• For (1, 1) The output will be (A00 + A11 + A22 + A20 + A02).
• For (2, 1) The output will be (A10 + A21 + A12 + A03)
• For right inclined diagonals
• Start from top left and keep covering all diagonals till bottom right.
• According to above illustration the ith right inclined diagonal contains following elements
• 0th diagonal = A00
• 1st diagonal  = A10+ A01
• 2nd diagonal = A20 + A11 + A02
• 3rd diagonal = A21 + A12 + A03
• 4th diagonal = A22 + A13
• 5th diagonal = A23
• Storing the above values in the vector right_inclined_digsum in the same order.
• In order to check the (x, y) element belonging to which diagonal just observe that Aij belongs to (i + j)th right inclined diagonal.
• For left inclined diagonals
• Start from bottom left and keep covering all diagonals till top right
• According to above illustration the ith left inclined diagonal contains following elements
• 0th diagonal = A20
• 1st diagonal = A10 + A21
• 2nd diagonal = A00 + A11 + A22
• 3rd diagonal = A01 + A12 + A23
• 4th diagonal = A02 + A13
• 5th diagonal = A03
• Storing the above values in the vector left_inclined_digsum in the same order.
• In order to check the (x, y) element belongs to which diagonal just observe that Aij belongs to (N – i + j – 1)th left inclined diagonal.
• After precomputing all these data, for each query of (x, y) output
•  right_inclined_digsum[x + y] + left_inclined_digsum[N – x + y – 1] – arr[x][y]

Follow the steps mentioned below to implement the idea:

• Create two vectors to store the diagonal sums (one for left inclined and the other for right inclined).
• Store the sum of the diagonals in the indices as shown above.
• Find the diagonals of which the current coordinate is a part.
• Calculate the sum as shown above.

Below is the implementation of the above approach.

## C++

 `// C++ code for the above approach:`   `#include ` `using` `namespace` `std;` `const` `int` `n = 4;` `const` `int` `m = 4;`   `// Function for diagonal sum` `int` `diagonal_sum(vector >& arr,` `                 ``vector<``int``>& right_inclined_digsum,` `                 ``vector<``int``>& left_inclined_digsum, ``int` `n,` `                 ``int` `x, ``int` `y)` `{` `    ``// To make it compatible with 0 based indexing` `    ``int` `a = (n - x) + y - 1;` `    ``int` `b = x + y;` `    ``int` `sum = right_inclined_digsum[b]` `              ``+ left_inclined_digsum[a] - arr[x][y];` `    ``return` `sum;` `}`   `// Precomputaion` `void` `precompute(``int` `n, ``int` `m, vector > arr,` `                ``vector<``int``>& right_inclined_digsum,` `                ``vector<``int``>& left_inclined_digsum)` `{`   `    ``// To cover all diagonals of (/) type` `    ``for` `(``int` `i = 0; i < n; i++) {` `        ``for` `(``int` `j = 0; j < m; j++) {` `            ``right_inclined_digsum[i + j] += arr[i][j];` `        ``}` `    ``}`   `    ``// To cover all diagonals of (\) type` `    ``for` `(``int` `i = n - 1; i >= 0; i--) {` `        ``for` `(``int` `j = 0; j < m; j++) {` `            ``left_inclined_digsum[n - 1 - i + j]` `                ``+= arr[i][j];` `        ``}`   `        ``// precomputaion done` `    ``}` `}`   `void` `solve(vector >& arr, ``int` `Q,` `           ``vector >& query)` `{` `    ``vector<``int``> right_inclined_digsum(n + m - 1, 0);` `    ``vector<``int``> left_inclined_digsum(n + m - 1, 0);`   `    ``// Function for precomputation` `    ``precompute(n, m, arr, right_inclined_digsum,` `               ``left_inclined_digsum);`   `    ``// Iterator for these coordinates` `    ``int` `it = 0;`   `    ``while` `(Q--) {` `        ``int` `x = query[it].first;` `        ``int` `y = query[it].second;` `        ``cout << diagonal_sum(arr, right_inclined_digsum,` `                             ``left_inclined_digsum, n, x, y)` `             ``<< ``"\n"``;` `        ``it++;` `    ``}` `}` `// Drivers code` `int` `main()` `{` `    ``vector > arr = { { 1, 2, 2, 1 },` `                                 ``{ 2, 4, 2, 4 },` `                                 ``{ 2, 2, 3, 1 },` `                                 ``{ 2, 4, 2, 4 } };` `    ``int` `Q = 3;`   `    ``// Defining coordinates for each query` `    ``vector > query;` `    ``query.push_back({ 0, 0 });` `    ``query.push_back({ 3, 1 });` `    ``query.push_back({ 3, 3 });`   `    ``// Function call` `    ``solve(arr, Q, query);` `    ``return` `0;` `}`

## Java

 `// Java code to implement the approach` `import` `java.io.*;` `import` `java.util.*;`   `class` `GFG {` `    ``static` `int` `n = ``4``;` `    ``static` `int` `m = ``4``;`   `    ``// Function for diagonal sum` `    ``static` `int` `diagonal_sum(``int``[][] arr,` `                            ``int``[] right_inclined_digsum,` `                            ``int``[] left_inclined_digsum,` `                            ``int` `n, ``int` `x, ``int` `y)` `    ``{` `        ``// To make it compatible with 0 based indexing` `        ``int` `a = (n - x) + y - ``1``;` `        ``int` `b = x + y;` `        ``int` `sum = right_inclined_digsum[b]` `                  ``+ left_inclined_digsum[a] - arr[x][y];` `        ``return` `sum;` `    ``}`   `    ``// Precomputaion` `    ``static` `void` `precompute(``int` `n, ``int` `m, ``int``[][] arr,` `                           ``int``[] right_inclined_digsum,` `                           ``int``[] left_inclined_digsum)` `    ``{`   `        ``// To cover all diagonals of (/) type` `        ``for` `(``int` `i = ``0``; i < n; i++) {` `            ``for` `(``int` `j = ``0``; j < m; j++) {` `                ``right_inclined_digsum[i + j] += arr[i][j];` `            ``}` `        ``}`   `        ``// To cover all diagonals of (\) type` `        ``for` `(``int` `i = n - ``1``; i >= ``0``; i--) {` `            ``for` `(``int` `j = ``0``; j < m; j++) {` `                ``left_inclined_digsum[n - ``1` `- i + j]` `                    ``+= arr[i][j];` `            ``}` `            ``// precomputaion done` `        ``}` `    ``}`   `    ``static` `void` `solve(``int``[][] arr, ``int` `Q, ``int``[][] query)` `    ``{` `        ``int``[] right_inclined_digsum = ``new` `int``[n + m - ``1``];` `        ``int``[] left_inclined_digsum = ``new` `int``[n + m - ``1``];`   `        ``// Function for precomputation` `        ``precompute(n, m, arr, right_inclined_digsum,` `                   ``left_inclined_digsum);`   `        ``// Iterator for these coordinates` `        ``int` `it = ``0``;`   `        ``while` `(Q-- > ``0``) {` `            ``int` `x = query[it][``0``];` `            ``int` `y = query[it][``1``];` `            ``System.out.println(diagonal_sum(` `                ``arr, right_inclined_digsum,` `                ``left_inclined_digsum, n, x, y));` `            ``it++;` `        ``}` `    ``}` `    ``// Driver code` `    ``public` `static` `void` `main(String[] args)` `    ``{` `        ``int``[][] arr = { { ``1``, ``2``, ``2``, ``1` `},` `                        ``{ ``2``, ``4``, ``2``, ``4` `},` `                        ``{ ``2``, ``2``, ``3``, ``1` `},` `                        ``{ ``2``, ``4``, ``2``, ``4` `} };` `        ``int` `Q = ``3``;`   `        ``// Defining coordinates for each query` `        ``int``[][] query = ``new` `int``[``3``][``2``];` `        ``query[``0``] = ``new` `int``[] { ``0``, ``0` `};` `        ``query[``1``] = ``new` `int``[] { ``3``, ``1` `};` `        ``query[``2``] = ``new` `int``[] { ``3``, ``3` `};`   `        ``// Function call` `        ``solve(arr, Q, query);` `    ``}` `}` `// This code is contributed by Karandeep1234`

## Python3

 `# Python code for the above approach`     `n ``=` `4` `m ``=` `4` `right_inclined_digsum ``=` `[``0``]``*``(n``+``m``-``1``)` `left_inclined_digsum ``=` `[``0``]``*``(n``+``m``-``1``)` `# Function for diagonal sum`     `def` `diagonal_sum(arr, right_inclined_digsum, left_inclined_digsum, n, x, y):` `    ``# To make it compatible with 0 based indexing` `    ``a ``=` `(n``-``x)``+``y``-``1` `    ``b ``=` `x``+``y` `    ``summ ``=` `right_inclined_digsum[b]``+``left_inclined_digsum[a]``-``arr[x][y]` `    ``return` `summ` `# Precomputaion function`     `def` `precompute(n, m, arr, right_inclined_digsum, left_inclined_digsum):` `    ``# To cover all diagonals of (/) type` `    ``for` `i ``in` `range``(n):` `        ``for` `j ``in` `range``(m):` `            ``right_inclined_digsum[i``+``j] ``+``=` `arr[i][j]` `    ``# To cover all diagonals of (\) type` `    ``for` `i ``in` `range``(n``-``1``, ``-``1``, ``-``1``):` `        ``for` `j ``in` `range``(``0``, m):` `            ``left_inclined_digsum[n``-``1``-``i``+``j] ``+``=` `arr[i][j]` `    ``# precomputaion done`     `def` `solve(arr, Q, query):` `    ``# Function for precomputation` `    ``precompute(n, m, arr, right_inclined_digsum, left_inclined_digsum)` `    ``# Iterator for these coordinates` `    ``it ``=` `0` `    ``while``(Q > ``0``):` `        ``x ``=` `query[it][``0``]` `        ``y ``=` `query[it][``1``]` `        ``print``(diagonal_sum(arr, right_inclined_digsum,` `                           ``left_inclined_digsum, n, x, y))` `        ``it ``+``=` `1` `        ``Q ``-``=` `1`     `# Drivers code` `if` `__name__ ``=``=` `"__main__"``:` `    ``arr ``=` `[[``1``, ``2``, ``2``, ``1``], [``2``, ``4``, ``2``, ``4``], [``2``, ``2``, ``3``, ``1``], [``2``, ``4``, ``2``, ``4``]]` `    ``Q ``=` `3` `    ``# Defining coordinates for each query` `    ``query ``=` `[]` `    ``query.append([``0``, ``0``])` `    ``query.append([``3``, ``1``])` `    ``query.append([``3``, ``3``])` `    ``# Function call` `    ``solve(arr, Q, query)` `" Code is written by RAJAT KUMAR [GLAU] "`

## C#

 `// C# code for the above approach:`   `using` `System;` `using` `System.Collections.Generic;`   `class` `pair {` `    ``public` `int` `first, second;` `    ``public` `pair(``int` `x, ``int` `y)` `    ``{` `        ``this``.first = x;` `        ``this``.second = y;` `    ``}` `}`   `class` `GFG {` `    ``static` `int` `n = 4;` `    ``static` `int` `m = 4;`   `    ``// Function for diagonal sum` `    ``static` `int` `diagonal_sum(``int``[, ] arr,` `                            ``List<``int``> right_inclined_digsum,` `                            ``List<``int``> left_inclined_digsum,` `                            ``int` `n, ``int` `x, ``int` `y)` `    ``{` `        ``// To make it compatible with 0 based indexing` `        ``int` `a = (n - x) + y - 1;` `        ``int` `b = x + y;` `        ``int` `sum = right_inclined_digsum[b]` `                  ``+ left_inclined_digsum[a] - arr[x, y];` `        ``return` `sum;` `    ``}`   `    ``// Precomputaion` `    ``static` `void` `precompute(``int` `n, ``int` `m, ``int``[, ] arr,` `                           ``List<``int``> right_inclined_digsum,` `                           ``List<``int``> left_inclined_digsum)` `    ``{`   `        ``// To cover all diagonals of (/) type` `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``for` `(``int` `j = 0; j < m; j++) {` `                ``right_inclined_digsum[i + j] += arr[i, j];` `            ``}` `        ``}`   `        ``// To cover all diagonals of (\) type` `        ``for` `(``int` `i = n - 1; i >= 0; i--) {` `            ``for` `(``int` `j = 0; j < m; j++) {` `                ``left_inclined_digsum[n - 1 - i + j]` `                    ``+= arr[i, j];` `            ``}`   `            ``// precomputaion done` `        ``}` `    ``}`   `    ``static` `void` `solve(``int``[, ] arr, ``int` `Q, List query)` `    ``{` `        ``List<``int``> right_inclined_digsum = ``new` `List<``int``>();` `        ``List<``int``> left_inclined_digsum = ``new` `List<``int``>();`   `        ``for` `(``int` `i = 0; i < n + m - 1; i++) {` `            ``right_inclined_digsum.Add(0);` `            ``left_inclined_digsum.Add(0);` `        ``}`   `        ``// Function for precomputation` `        ``precompute(n, m, arr, right_inclined_digsum,` `                   ``left_inclined_digsum);`   `        ``// Iterator for these coordinates` `        ``int` `it = 0;`   `        ``while` `(Q > 0) {` `            ``Q--;` `            ``int` `x = query[it].first;` `            ``int` `y = query[it].second;` `            ``Console.WriteLine(diagonal_sum(` `                ``arr, right_inclined_digsum,` `                ``left_inclined_digsum, n, x, y));` `            ``it++;` `        ``}` `    ``}` `    ``// Drivers code` `    ``public` `static` `void` `Main(``string``[] args)` `    ``{` `        ``int``[, ] arr = { { 1, 2, 2, 1 },` `                        ``{ 2, 4, 2, 4 },` `                        ``{ 2, 2, 3, 1 },` `                        ``{ 2, 4, 2, 4 } };` `        ``int` `Q = 3;`   `        ``// Defining coordinates for each query` `        ``List query = ``new` `List();` `        ``query.Add(``new` `pair(0, 0));` `        ``query.Add(``new` `pair(3, 1));` `        ``query.Add(``new` `pair(3, 3));`   `        ``// Function call` `        ``solve(arr, Q, query);` `    ``}` `}`   `// This code is contributed by phasing17`

## Javascript

 ``

Output

```12
13
12```

Time Complexity: O(Q + N * M)
Auxiliary Space: O(N + M)

My Personal Notes arrow_drop_up