Binary Matrix after flipping submatrices in given range for Q queries

Given a binary matrix arr[][] of dimensions M x N and Q queries of the form (x1, y1, x2, y2), where (x1, y1) and (x2, y2) denotes the top-left and bottom-right indices of the submatrix required to be flipped(convert 0s to 1s and vice versa) respectively. The task is to print the final matrix obtained after performing given Q queries
Examples:

Input: arr[][] = {{0, 1, 0}, {1, 1, 0}}, queries[][] = {{1, 1, 2, 3}}
Output: [[1, 0, 1], [0, 0, 1]]
Explanation:
The submatrix to be flipped is equal to {{0, 1, 0}, {1, 1, 0}} 
The flipped matrix is {{1, 0, 1}, {0, 0, 1}}.

Input: arr[][] = {{0, 1, 0}, {1, 1, 0}}, queries[][] = {{1, 1, 2, 3}, {1, 1, 1, 1], {1, 2, 2, 3}}
Output: [[0, 1, 0], [0, 1, 0]]
Explanation:
Query 1:
Submatrix to be flipped = [[0, 1, 0], [1, 1, 0]] 
Flipped submatrix is [[1, 0, 1], [0, 0, 1]]. 
Therefore, the modified matrix is [[1, 0, 1], [0, 0, 1]].
Query 2: 
Submatrix to be flipped = [[1]] 
Flipped submatrix is [[0]] 
Therefore, matrix is [[0, 0, 1], [0, 0, 1]].
Query 3:
Submatrix to be flipped = [[0, 1], [0, 1]] 
Flipped submatrix is [[1, 0], [1, 0]] 
Therefore, modified matrix is [[0, 1, 0], [0, 1, 0]].

Naive Approach: The simplest approach to solve the problem for each query is to iterate over the given submatrices and for every element, check if it is 0 or 1, and flip accordingly. After completing these operations for all the queries, print the final matrix obtained.

Below is the implementation of the above approach :



filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to implement
// the above approach
#include<bits/stdc++.h>
using namespace std;
 
// Function to flip a submatrices
void manipulation(vector<vector<int>> &matrix,
                         vector<int> &q)
{
   
  // Boundaries of the submatrix
  int x1 = q[0], y1 = q[1],
      x2 = q[2], y2 = q[3];
 
  // Iterate over the submatrix
  for(int i = x1 - 1; i < x2; i++)
  {
    for(int j = y1 - 1; j < y2; j++)
    {
       
      // Check for 1 or 0
      // and flip accordingly
      if (matrix[i][j] == 1)
        matrix[i][j] = 0;
      else
        matrix[i][j] = 1;
    }
  }
}
 
// Function to perform the queries
void queries_fxn(vector<vector<int>> &matrix,
                 vector<vector<int>> &queries)
{
  for(auto q : queries)
    manipulation(matrix, q);       
}
 
// Driver code
int main()
{
  vector<vector<int>> matrix = { { 0, 1, 0 },
                                 { 1, 1, 0 } };
  vector<vector<int>> queries = { { 1, 1, 2, 3 },
                                  { 1, 1, 1, 1 },
                                  { 1, 2, 2, 3 } };
   
  // Function call
  queries_fxn(matrix, queries);
  cout << "[";
 
  for(int i = 0; i < matrix.size(); i++)
  {
    cout << "["
    for(int j = 0; j < matrix[i].size(); j++)
      cout << matrix[i][j] << " ";
 
    if (i == matrix.size() - 1)
      cout << "]";
    else
      cout << "], ";
  }
   cout << "]";
}
 
// This code is contributed by bgangwar59
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to implement
// the above approach
import java.util.*;
import java.lang.*;
class GFG{
 
// Function to flip a submatrices
static void manipulation(int[][] matrix,
                         int[] q)
{
  // Boundaries of the submatrix
  int x1 = q[0], y1 = q[1],
      x2 = q[2], y2 = q[3];
 
  // Iterate over the submatrix
  for(int i = x1 - 1; i < x2; i++)
  {
    for(int j = y1 - 1; j < y2; j++)
    {
      // Check for 1 or 0
      // and flip accordingly
      if (matrix[i][j] == 1)
        matrix[i][j] = 0;
      else
        matrix[i][j] = 1;
    }
  }
}
 
// Function to perform the queries
static void queries_fxn(int[][] matrix,
                        int[][] queries)
{
  for(int[] q : queries)
    manipulation(matrix, q);       
}
 
// Driver code
public static void main (String[] args)
{
  int[][] matrix = {{0, 1, 0}, {1, 1, 0}};
  int[][] queries = {{1, 1, 2, 3},
                     {1, 1, 1, 1},
                     {1, 2, 2, 3}};
 
  // Function call
  queries_fxn(matrix, queries);
  System.out.print("[");
 
  for(int i = 0; i < matrix.length; i++)
  {
    System.out.print("["); 
    for(int j = 0; j < matrix[i].length; j++)
      System.out.print(matrix[i][j] + " ");
 
    if(i == matrix.length - 1)
      System.out.print("]");
    else
      System.out.print("], ");
  }
  System.out.print("]");
}
}
 
// This code is contributed by offbeat
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 Program to implement
# the above approach
 
# Function to flip a submatrices
def manipulation(matrix, q):
 
    # Boundaries of the submatrix
    x1, y1, x2, y2 = q
 
    # Iterate over the submatrix
    for i in range(x1-1, x2):
        for j in range(y1-1, y2):
 
            # Check for 1 or 0
            # and flip accordingly
            if matrix[i][j]:
                matrix[i][j] = 0
            else:
                matrix[i][j] = 1
 
# Function to perform the queries
def queries_fxn(matrix, queries):
    for q in queries:
        manipulation(matrix, q)
 
 
# Driver Code
matrix = [[0, 1, 0], [1, 1, 0]]
queries = [[1, 1, 2, 3], \
           [1, 1, 1, 1], \
           [1, 2, 2, 3]]
 
# Function call
queries_fxn(matrix, queries)
print(matrix)
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to implement
// the above approach
using System;
 
class GFG{
 
// Function to flip a submatrices
static void manipulation(int[,] matrix,
                         int[] q)
{
     
    // Boundaries of the submatrix
    int x1 = q[0], y1 = q[1],
        x2 = q[2], y2 = q[3];
     
    // Iterate over the submatrix
    for(int i = x1 - 1; i < x2; i++)
    {
        for(int j = y1 - 1; j < y2; j++)
        {
             
            // Check for 1 or 0
            // and flip accordingly
            if (matrix[i, j] == 1)
                matrix[i, j] = 0;
            else
                matrix[i, j] = 1;
        }
    }
}
 
public static int[] GetRow(int[,] matrix, int row)
{
    var rowLength = matrix.GetLength(1);
    var rowVector = new int[rowLength];
     
    for(var i = 0; i < rowLength; i++)
        rowVector[i] = matrix[row, i];
     
    return rowVector;
}
 
// Function to perform the queries
static void queries_fxn(int[,] matrix,
                        int[,] queries)
{
    for(int i = 0; i < queries.GetLength(0); i++)
        manipulation(matrix, GetRow(queries, i));       
}
 
// Driver code
public static void Main(String[] args)
{
    int[,] matrix = { { 0, 1, 0 },
                      { 1, 1, 0 } };
    int[,] queries = { { 1, 1, 2, 3 },
                       { 1, 1, 1, 1 },
                       { 1, 2, 2, 3 } };
     
    // Function call
    queries_fxn(matrix, queries);
    Console.Write("[");
     
    for(int i = 0; i < matrix.GetLength(0); i++)
    {
        Console.Write("["); 
        for(int j = 0; j < matrix.GetLength(1); j++)
            Console.Write(matrix[i, j] + ", ");
         
        if (i == matrix.Length - 1)
            Console.Write("]");
        else
            Console.Write("], ");
    }
    Console.Write("]");
}
}
 
// This code is contributed by Princi Singh
chevron_right

Output: 
[[0, 1, 0], [0, 1, 0]]









 

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

Efficient Approach: The above approach can be optimized using Dynamic programming and Prefix Sum technique. Mark the boundaries of the submatrices involved in each query and then calculate prefix sum of the operations involved in the matrix and update the matrix accordingly. Follow the steps below to solve the problem:  

dp[i][j] = dp[i][j] + dp[i-1][j] + dp[i][j – 1] – dp[i – 1][j – 1] 
 

Below is the implementation of the above approach : 

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to implement
# the above approach
 
# Function to modify dp[][] array by
# generating prefix sum
def modifyDP(matrix, dp):
     
    for j in range(1, len(matrix)+1):
         
        for k in range(1, len(matrix[0])+1):
             
            # Update the tabular data
            dp[j][k] = dp[j][k] + dp[j-1][k] \
            + dp[j][k-1]-dp[j-1][k-1]
             
            # If the count of flips is even
            if dp[j][k] % 2 != 0:
                matrix[j-1][k-1] = int(matrix[j-1][k-1]) ^ 1
 
# Function to update dp[][] matrix
# for each query
def queries_fxn(matrix, queries, dp):
    for q in queries:
        x1, y1, x2, y2 = q
         
        # Update the table
        dp[x1][y1] += 1
        dp[x2 + 1][y2 + 1] += 1
        dp[x1][y2 + 1] -= 1
        dp[x2 + 1][y1] -= 1
         
    modifyDP(matrix, dp)
 
 
# Driver Code
matrix = [[0, 1, 0], [1, 1, 0]]
queries = [[1, 1, 2, 3], \
           [1, 1, 1, 1], \
           [1, 2, 2, 3]]
 
# Initialize dp table
dp = [[0 for i in range(len(matrix[0])+2)] \
for j in range(len(matrix)+2)]
 
queries_fxn(matrix, queries, dp)
print(matrix)
chevron_right

Output: 
[[0, 1, 0], [0, 1, 0]]









 

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

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.





Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : offbeat, princi singh, bgangwar59

Article Tags :