Open In App

Binary Matrix after flipping submatrices in given range for Q queries

Improve
Improve
Like Article
Like
Save
Share
Report

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 the 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, the 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, the 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 :

C++




// 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


Java




// 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


Python3




# 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)


C#




// 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


Javascript




<script>
// Javascript program to implement
// the above approach
 
// Function to flip a submatrices
function manipulation(matrix, q) {
 
    // Boundaries of the submatrix
    let x1 = q[0], y1 = q[1],
        x2 = q[2], y2 = q[3];
 
    // Iterate over the submatrix
    for (let i = x1 - 1; i < x2; i++) {
        for (let 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
function queries_fxn(matrix, queries) {
    for (let q of queries)
        manipulation(matrix, q);
}
 
// Driver code
 
let matrix = [[0, 1, 0],
              [1, 1, 0]];
let queries = [[1, 1, 2, 3],
               [1, 1, 1, 1],
               [1, 2, 2, 3]];
 
// Function call
queries_fxn(matrix, queries);
document.write("[");
 
for (let i = 0; i < matrix.length; i++) {
    document.write("[");
    for (let j = 0; j < matrix[i].length; j++) {
        if (j < matrix[i].length - 1) {
            document.write(matrix[i][j] + ", ");
        }
        else {
            document.write(matrix[i][j] + " ");
        }
    }
 
    if (i == matrix.length - 1)
        document.write("]");
    else
        document.write("], ");
}
document.write("]");
 
 
 
// This code is contributed by _saurabh_jaiswal
</script>


Output: 

[[0, 1, 0], [0, 1, 0]]

 

Time complexity: O( N * M * Q), The time complexity of the given program is O(N*M*Q), where N is the number of queries, M is the number of rows in the matrix, and Q is the number of columns in the matrix. This is because we need to iterate over each element in the submatrix for each query, which takes O(N*M) time, and we have Q queries to perform. 
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 the prefix sum of the operations involved in the matrix and update the matrix accordingly. Follow the steps below to solve the problem:  

  • Initialize a 2D state space table dp[][] to store the count of flips at respective indices of the matrix
  • For each query {x1, y1, x2, y2, K}, update the dp[][] matrix by the following operations: 
    • dp[x1][y1] += 1
    • dp[x2 + 1][y1] -= 1
    • dp[x2 + 1][y2 + 1] += 1
    • dp[x1][y2 + 1] -= 1
  • Now, traverse over the dp[][] matrix and update dp[i][j] by calculating the prefix sum of the rows and columns and diagonals by the following relation:

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

  • If dp[i][j] is found to be odd, reduce mat[i – 1][j – 1] by 1.
  • Finally, print the updated matrix mat[][] as the result.

Below is the implementation of the above approach :

C++




// C++ code for the above approach
#include <iostream>
#include <vector>
using namespace std;
 
// Function to modify dp[][] array by
// generating prefix sum
void modifyDP(vector<vector<int> >& matrix,
              vector<vector<int> >& dp)
{
  int row = matrix.size();
  int col = matrix[0].size();
  for (int j = 1; j <= row; j++) {
    for (int k = 1; k <= col; k++) {
      // 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]
          = matrix[j - 1][k - 1] ^ 1;
      }
    }
  }
}
 
// Function to update dp[][] matrix
// for each query
void queries_fxn(vector<vector<int> >& matrix,
                 vector<vector<int> >& queries,
                 vector<vector<int> >& dp)
{
  for (int i = 0; i < queries.size(); i++) {
    int x1 = queries[i][0];
    int y1 = queries[i][1];
    int x2 = queries[i][2];
    int y2 = queries[i][3];
 
    // 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
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 } };
 
  // Initialize dp table
  vector<vector<int> > dp(
    matrix.size() + 2,
    vector<int>(matrix[0].size() + 2, 0));
 
  queries_fxn(matrix, queries, dp);
  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 << "], ";
    }
  }
}
 
// This code is contributed by lokeshpotta20.


Java




import java.util.*;
import java.io.*;
 
// Java program for the above approach
class GFG{
 
  // Function to modify dp[][] array by
  // generating prefix sum
  static void modifyDP(int matrix[][], int dp[][]){
 
    for(int j = 1 ; j <= matrix.length ; j++){
 
      for(int k = 1 ; k <= matrix[0].length ; k++){
 
        // 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] = matrix[j-1][k-1] ^ 1;
        }
      }
    }
  }
 
  // Function to update dp[][] matrix
  // for each query
  static void queries_fxn(int matrix[][], int queries[][], int dp[][]){
    for(int i = 0 ; i < queries.length ; i++){
      int x1 = queries[i][0];
      int y1 = queries[i][1];
      int x2 = queries[i][2];
      int y2 = queries[i][3];
 
      // 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
  public static void main(String args[])
  {
    int matrix[][] = new int[][]{
      new int[]{0, 1, 0},
      new int[]{1, 1, 0}
    };
    int queries[][] = new int[][]{
      new int[]{1, 1, 2, 3},
      new int[]{1, 1, 1, 1},
      new int[]{1, 2, 2, 3}
    };
 
    // Initialize dp table
    int dp[][] = new int[(matrix.length + 2)][(matrix[0].length + 2)];
 
    queries_fxn(matrix, queries, dp);
    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 entertain2022.


Python3




# 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)


C#




// C# code for the above approach
using System;
 
class GFG
{
    // Function to modify dp[][] array by generating prefix sum
    static void ModifyDP(int[,] matrix, int[,] dp)
    {
        for (int j = 1; j <= matrix.GetLength(0); j++)
        {
            for (int k = 1; k <= matrix.GetLength(1); k++)
            {
                // 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] = matrix[j - 1, k - 1] ^ 1;
                }
            }
        }
    }
 
    // Function to update dp[][] matrix for each query
    static void QueriesFxn(int[,] matrix, int[,] queries, int[,] dp)
    {
        for (int i = 0; i < queries.GetLength(0); i++)
        {
            int x1 = queries[i, 0];
            int y1 = queries[i, 1];
            int x2 = queries[i, 2];
            int y2 = queries[i, 3];
 
            // 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
    public static void Main(string[] args)
    {
        int[,] matrix = new int[,] { { 0, 1, 0 }, { 1, 1, 0 } };
        int[,] queries = new int[,] { { 1, 1, 2, 3 }, { 1, 1, 1, 1 }, { 1, 2, 2, 3 } };
 
        // Initialize dp table
        int[,] dp = new int[(matrix.GetLength(0) + 2, matrix.GetLength(1) + 2)];
 
        QueriesFxn(matrix, queries, dp);
        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.GetLength(0) - 1)
            {
                Console.Write("]");
            }
            else
            {
                Console.Write("], ");
            }
        }
        Console.Write("]");
    }
}
 
// This code is contributed by pradeepkumarppk2003.


Javascript




// Javascript code for the above approach
 
// Function to modify dp[][] array by
// generating prefix sum
function modifyDP(matrix, dp)
{
  let row = matrix.length;
  let col = matrix[0].length;
  for (let j = 1; j <= row; j++) {
    for (let k = 1; k <= col; k++) {
      // 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]
          = matrix[j - 1][k - 1] ^ 1;
      }
    }
  }
}
 
// Function to update dp[][] matrix
// for each query
function queries_fxn(matrix, queries, dp)
{
  for (let i = 0; i < queries.length; i++) {
    let x1 = queries[i][0];
    let y1 = queries[i][1];
    let x2 = queries[i][2];
    let y2 = queries[i][3];
 
    // 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
let matrix = [[0, 1, 0 ], [ 1, 1, 0]];
let queries = [ [ 1, 1, 2, 3 ],[1, 1, 1, 1 ],[1, 2, 2, 3 ]];
 
  // Initialize dp table
  let dp=new Array(matrix.length + 2);
  for(let i=0; i<matrix.length+2; i++)
    dp[i]=new Array(matrix[0].length+2).fill(0);
 
  queries_fxn(matrix, queries, dp);
  document.write("[");
  for (let i = 0; i < matrix.length; i++) {
    document.write("[");
    for (let j = 0; j < matrix[i].length; j++) {
      document.write(matrix[i][j] + " ");
    }
    if (i == matrix.length - 1) {
      document.write("]");
    }
    else {
      document.write("], ");
    }
  }


Output: 

[[0, 1, 0], [0, 1, 0]]

 

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



Last Updated : 08 May, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads