Open In App

Queries to find the count of connected Non-Empty Cells in a Matrix with updates

Improve
Improve
Like Article
Like
Save
Share
Report

Given a boolean matrix mat[][] consisting of N rows and M columns, initially filled with 0‘s(empty cells), an integer K and queries Q[][] of the type {X, Y}, the task is to replace mat[X][Y] = 1(non-empty cells) and count the number of connected non-empty cells from the given matrix.
Examples: 

Input: N = 3, M = 3, K = 4, Q[][] = {{0, 0}, {1, 1}, {1, 0}, {1, 2}} 
Output: 1 2 1 1 
Explanation: 
Initially, mat[][] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}} 
Query 1: mat[][] = {{1, 0, 0}, {0, 0, 0}, {0, 0, 0}}, Count = 1 
Query 1: mat[][] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 0}}, Count = 2 
Query 1: mat[][] = {{1, 0, 0}, {1, 1, 0}, {0, 0, 0}}, Count = 1 
Query 1: mat[][] = {{1, 0, 0}, {1, 1, 1}, {0, 0, 0}}, Count = 1
Input: N = 2, M = 2, K = 2, Q[][] = {{0, 0}, {0, 1}} 
Output : 1 1 
 

Approach: 
The problem can be solved using Disjoint Set Data Structure. Follow the steps below to solve the problem:  

  • Since, initially, there are no 1‘s in the matrix, count = 0.
  • Transform the two-dimension problem into the classic Union-find, by performing a linear mapping index = X * M + Y, where M is the column length.
  • After setting an index in each query, increment count.
  • If a non-empty cell is present in any of the 4 adjacent cells: 
    • Perform Union operation for the current index and adjacent cell(connecting two Sets).
    • Decrement count as two Sets are connected.

Below is the implementation of the above approach:

C++




// C++ program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Count of connected cells
int ctr = 0;
 
// Function to return the representative
// of the Set to which x belongs
int find(vector<int>& parent, int x)
{
 
    // If x is parent of itself
    if (parent[x] == x)
 
        // x is representative
        // of the Set
        return x;
 
    // Otherwise
    parent[x] = find(parent, parent[x]);
 
    // Path Compression
    return parent[x];
}
 
// Unites the set that includes
// x and the set that includes y
void setUnion(vector<int>& parent,
              vector<int>& rank, int x, int y)
{
    // Find the representatives(or the
    // root nodes) for x an y
    int parentx = find(parent, x);
    int parenty = find(parent, y);
 
    // If both are in the same set
    if (parenty == parentx)
        return;
 
    // Decrement count
    ctr--;
 
    // If x's rank is less than y's rank
    if (rank[parentx] < rank[parenty]) {
        parent[parentx] = parenty;
    }
 
    // Otherwise
    else if (rank[parentx] > rank[parenty]) {
        parent[parenty] = parentx;
    }
    else {
 
        // Then move x under y (doesn't matter
        // which one goes where)
        parent[parentx] = parenty;
 
        // And increment the result tree's
        // rank by 1
        rank[parenty]++;
    }
}
 
// Function to count the number of
// connected cells in the matrix
vector<int> solve(int n, int m,
                  vector<pair<int, int> >& query)
{
 
    // Store result for queries
    vector<int> result(query.size());
 
    // Store representative of
    // each element
    vector<int> parent(n * m);
 
    // Initially, all elements
    // are in their own set
    for (int i = 0; i < n * m; i++)
        parent[i] = i;
 
    // Stores the rank(depth) of each node
    vector<int> rank(n * m, 1);
 
    vector<bool> grid(n * m, 0);
 
    for (int i = 0; i < query.size(); i++) {
 
        int x = query[i].first;
        int y = query[i].second;
 
        // If the grid[x*m + y] is already
        // set, store the result
        if (grid[m * x + y] == 1) {
            result[i] = ctr;
            continue;
        }
 
        // Set grid[x*m + y] to 1
        grid[m * x + y] = 1;
 
        // Increment count.
        ctr++;
 
        // Check for all adjacent cells
        // to do a Union with neighbour's
        // set if neighbour is also 1
        if (x > 0 and grid[m * (x - 1) + y] == 1)
            setUnion(parent, rank,
                     m * x + y, m * (x - 1) + y);
 
        if (y > 0 and grid[m * (x) + y - 1] == 1)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y - 1);
 
        if (x < n - 1 and grid[m * (x + 1) + y] == 1)
            setUnion(parent, rank,
                     m * x + y, m * (x + 1) + y);
 
        if (y < m - 1 and grid[m * (x) + y + 1] == 1)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y + 1);
 
        // Store result.
        result[i] = ctr;
    }
    return result;
}
 
// Driver Code
int main()
{
    int N = 3, M = 3, K = 4;
 
    vector<pair<int, int> > query
        = { { 0, 0 },
            { 1, 1 },
            { 1, 0 },
            { 1, 2 } };
    vector<int> result = solve(N, M, query);
 
    for (int i = 0; i < K; i++)
        cout << result[i] << " ";
}


Java




// Java program to implement
// the above approach
import java.util.*;
 
class GFG{
 
// Count of connected cells
static int ctr = 0;
 
// Function to return the representative
// of the Set to which x belongs
static int find(int []parent, int x)
{
     
    // If x is parent of itself
    if (parent[x] == x)
 
        // x is representative
        // of the Set
        return x;
 
    // Otherwise
    parent[x] = find(parent, parent[x]);
 
    // Path Compression
    return parent[x];
}
 
// Unites the set that includes
// x and the set that includes y
static void setUnion(int[] parent,
                     int[] rank, int x, int y)
{
     
    // Find the representatives(or the
    // root nodes) for x an y
    int parentx = find(parent, x);
    int parenty = find(parent, y);
 
    // If both are in the same set
    if (parenty == parentx)
        return;
 
    // Decrement count
    ctr--;
 
    // If x's rank is less than y's rank
    if (rank[parentx] < rank[parenty])
    {
        parent[parentx] = parenty;
    }
 
    // Otherwise
    else if (rank[parentx] > rank[parenty])
    {
        parent[parenty] = parentx;
    }
    else
    {
         
        // Then move x under y (doesn't matter
        // which one goes where)
        parent[parentx] = parenty;
 
        // And increment the result tree's
        // rank by 1
        rank[parenty]++;
    }
}
 
// Function to count the number of
// connected cells in the matrix
static int [] solve(int n, int m,
                    int [][]query)
{
     
    // Store result for queries
    int []result = new int[query.length];
     
    // Store representative of
    // each element
    int []parent = new int[n * m];
 
    // Initially, all elements
    // are in their own set
    for(int i = 0; i < n * m; i++)
        parent[i] = i;
 
    // Stores the rank(depth) of each node
    int []rank = new int[n * m];
    Arrays.fill(rank, 1);
     
    boolean []grid = new boolean[n * m];
 
    for(int i = 0; i < query.length; i++)
    {
        int x = query[i][0];
        int y = query[i][1];
 
        // If the grid[x*m + y] is already
        // set, store the result
        if (grid[m * x + y] == true)
        {
            result[i] = ctr;
            continue;
        }
 
        // Set grid[x*m + y] to 1
        grid[m * x + y] = true;
 
        // Increment count.
        ctr++;
 
        // Check for all adjacent cells
        // to do a Union with neighbour's
        // set if neighbour is also 1
        if (x > 0 && grid[m * (x - 1) + y] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x - 1) + y);
 
        if (y > 0 && grid[m * (x) + y - 1] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y - 1);
 
        if (x < n - 1 && grid[m * (x + 1) + y] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x + 1) + y);
 
        if (y < m - 1 && grid[m * (x) + y + 1] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y + 1);
 
        // Store result.
        result[i] = ctr;
    }
    return result;
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 3, M = 3, K = 4;
 
    int [][]query = { { 0, 0 },
                      { 1, 1 },
                      { 1, 0 },
                      { 1, 2 } };
    int[] result = solve(N, M, query);
 
    for(int i = 0; i < K; i++)
        System.out.print(result[i] + " ");
}
}
 
// This code is contributed by Amit Katiyar


Python3




# Python 3 program to implement
# the above approach
 
# Count of connected cells
ctr = 0
 
# Function to return the
# representative of the Set
# to which x belongs
def find(parent, x):
 
    # If x is parent of itself
    if (parent[x] == x):
 
        # x is representative
        # of the Set
        return x
 
    # Otherwise
    parent[x] = find(parent,
                     parent[x])
 
    # Path Compression
    return parent[x]
 
# Unites the set that
# includes x and the
# set that includes y
def setUnion(parent,
             rank, x, y):
 
    global ctr
     
    # Find the representatives
    # (or the root nodes) for x an y
    parentx = find(parent, x)
    parenty = find(parent, y)
 
    # If both are in the same set
    if (parenty == parentx):
        return
 
    # Decrement count
    ctr -= 1
 
    # If x's rank is less than y's rank
    if (rank[parentx] < rank[parenty]):
        parent[parentx] = parenty
    
    # Otherwise
    elif (rank[parentx] > rank[parenty]):
        parent[parenty] = parentx
     
    else:
 
        # Then move x under y
        # (doesn't matter which
        # one goes where)
        parent[parentx] = parenty
 
        # And increment the result
        # tree's rank by 1
        rank[parenty] += 1
   
# Function to count the number of
# connected cells in the matrix
def solve(n, m, query):
 
    global ctr
     
    # Store result for queries
    result = [0] * len(query)
 
    # Store representative of
    # each element
    parent = [0] * (n * m)
 
    # Initially, all elements
    # are in their own set
    for i in range (n * m):
        parent[i] = i
 
    # Stores the rank(depth)
    # of each node
    rank = [1] * (n * m)
   
    grid = [0] * (n * m)
 
    for  i in range (len( query)):
        x = query[i][0]
        y = query[i][1]
 
        # If the grid[x*m + y] is already
        # set, store the result
        if (grid[m * x + y] == 1):
            result[i] = ctr
            continue
        
        # Set grid[x*m + y] to 1
        grid[m * x + y] = 1
 
        # Increment count.
        ctr += 1
 
        # Check for all adjacent cells
        # to do a Union with neighbour's
        # set if neighbour is also 1
        if (x > 0 and
            grid[m * (x - 1) + y] == 1):
            setUnion(parent, rank,
                     m * x + y,
                     m * (x - 1) + y)
 
        if (y > 0 and
            grid[m * (x) + y - 1] == 1):
            setUnion(parent, rank,
                     m * x + y,
                     m * (x) + y - 1)
 
        if (x < n - 1 and
            grid[m * (x + 1) + y] == 1):
            setUnion(parent, rank,
                     m * x + y,
                     m * (x + 1) + y)
 
        if (y < m - 1 and
            grid[m * (x) + y + 1] == 1):
            setUnion(parent, rank,
                     m * x + y,
                     m * (x) + y + 1)
 
        # Store result.
        result[i] = ctr
    return result
 
# Driver Code
if __name__ == "__main__":
       
    N = 3
    M = 3
    K = 4
    query = [[0, 0],
             [1, 1],
             [1, 0],
             [1, 2]]
    result = solve(N, M, query)
    for i in range (K):
        print (result[i], end = " ")
         
# This code is contributed by Chitranayal


C#




// C# program to implement
// the above approach
using System;
class GFG{
 
// Count of connected cells
static int ctr = 0;
 
// Function to return the representative
// of the Set to which x belongs
static int find(int []parent, int x)
{
     
    // If x is parent of itself
    if (parent[x] == x)
 
        // x is representative
        // of the Set
        return x;
 
    // Otherwise
    parent[x] = find(parent, parent[x]);
 
    // Path Compression
    return parent[x];
}
 
// Unites the set that includes
// x and the set that includes y
static void setUnion(int[] parent,
                     int[] rank,
                     int x, int y)
{
     
    // Find the representatives(or the
    // root nodes) for x an y
    int parentx = find(parent, x);
    int parenty = find(parent, y);
 
    // If both are in the same set
    if (parenty == parentx)
        return;
 
    // Decrement count
    ctr--;
 
    // If x's rank is less than y's rank
    if (rank[parentx] < rank[parenty])
    {
        parent[parentx] = parenty;
    }
 
    // Otherwise
    else if (rank[parentx] > rank[parenty])
    {
        parent[parenty] = parentx;
    }
    else
    {
         
        // Then move x under y (doesn't matter
        // which one goes where)
        parent[parentx] = parenty;
 
        // And increment the result tree's
        // rank by 1
        rank[parenty]++;
    }
}
 
// Function to count the number of
// connected cells in the matrix
static int [] solve(int n, int m,
                    int [,]query)
{
     
    // Store result for queries
    int []result = new int[query.Length];
     
    // Store representative of
    // each element
    int []parent = new int[n * m];
 
    // Initially, all elements
    // are in their own set
    for(int i = 0; i < n * m; i++)
        parent[i] = i;
 
    // Stores the rank(depth) of each node
    int []rank = new int[n * m];
    for(int i = 0; i < rank.Length; i++)
        rank[i] = 1;
    bool []grid = new bool[n * m];
 
    for(int i = 0; i < query.GetLength(0); i++)
    {
        int x = query[i, 0];
        int y = query[i, 1];
 
        // If the grid[x*m + y] is already
        // set, store the result
        if (grid[m * x + y] == true)
        {
            result[i] = ctr;
            continue;
        }
 
        // Set grid[x*m + y] to 1
        grid[m * x + y] = true;
 
        // Increment count.
        ctr++;
 
        // Check for all adjacent cells
        // to do a Union with neighbour's
        // set if neighbour is also 1
        if (x > 0 && grid[m * (x - 1) + y] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x - 1) + y);
 
        if (y > 0 && grid[m * (x) + y - 1] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y - 1);
 
        if (x < n - 1 && grid[m * (x + 1) + y] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x + 1) + y);
 
        if (y < m - 1 && grid[m * (x) + y + 1] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y + 1);
 
        // Store result.
        result[i] = ctr;
    }
    return result;
}
 
// Driver Code
public static void Main(String[] args)
{
    int N = 3, M = 3, K = 4;
 
    int [,]query = {{ 0, 0 }, { 1, 1 },
                    { 1, 0 }, { 1, 2 }};
    int[] result = solve(N, M, query);
 
    for(int i = 0; i < K; i++)
        Console.Write(result[i] + " ");
}
}
 
// This code is contributed by sapnasingh4991


Javascript




<script>
 
// Javascript program to implement
// the above approach
 
// Count of connected cells
let ctr = 0;
 
// Function to return the representative
// of the Set to which x belongs
function find(parent,x)
{
    // If x is parent of itself
    if (parent[x] == x)
  
        // x is representative
        // of the Set
        return x;
  
    // Otherwise
    parent[x] = find(parent, parent[x]);
  
    // Path Compression
    return parent[x];
}
 
// Unites the set that includes
// x and the set that includes y
function setUnion(parent,rank,x,y)
{
    // Find the representatives(or the
    // root nodes) for x an y
    let parentx = find(parent, x);
    let parenty = find(parent, y);
  
    // If both are in the same set
    if (parenty == parentx)
        return;
  
    // Decrement count
    ctr--;
  
    // If x's rank is less than y's rank
    if (rank[parentx] < rank[parenty])
    {
        parent[parentx] = parenty;
    }
  
    // Otherwise
    else if (rank[parentx] > rank[parenty])
    {
        parent[parenty] = parentx;
    }
    else
    {
          
        // Then move x under y (doesn't matter
        // which one goes where)
        parent[parentx] = parenty;
  
        // And increment the result tree's
        // rank by 1
        rank[parenty]++;
    }
}
 
// Function to count the number of
// connected cells in the matrix
function solve(n,m,query)
{
    // Store result for queries
    let result = new Array(query.length);
      
    // Store representative of
    // each element
    let parent = new Array(n * m);
  
    // Initially, all elements
    // are in their own set
    for(let i = 0; i < n * m; i++)
        parent[i] = i;
  
    // Stores the rank(depth) of each node
    let rank = new Array(n * m);
     
    let grid = new Array(n * m);
      
    for(let i=0;i<(n*m);i++)
    {
        rank[i]=0;
        grid[i]=false;
    }
     
     
    for(let i = 0; i < query.length; i++)
    {
        let x = query[i][0];
        let y = query[i][1];
  
        // If the grid[x*m + y] is already
        // set, store the result
        if (grid[m * x + y] == true)
        {
            result[i] = ctr;
            continue;
        }
  
        // Set grid[x*m + y] to 1
        grid[m * x + y] = true;
  
        // Increment count.
        ctr++;
  
        // Check for all adjacent cells
        // to do a Union with neighbour's
        // set if neighbour is also 1
        if (x > 0 && grid[m * (x - 1) + y] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x - 1) + y);
  
        if (y > 0 && grid[m * (x) + y - 1] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y - 1);
  
        if (x < n - 1 && grid[m * (x + 1) + y] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x + 1) + y);
  
        if (y < m - 1 && grid[m * (x) + y + 1] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y + 1);
  
        // Store result.
        result[i] = ctr;
    }
    return result;
}
 
// Driver Code
let N = 3, M = 3, K = 4;
let query = [[ 0, 0 ],
                      [ 1, 1 ],
                      [ 1, 0 ],
                      [ 1, 2 ]];
                       
let result = solve(N, M, query);
for(let i = 0; i < K; i++)
    document.write(result[i] + " ");
 
// This code is contributed by avanitrachhadiya2155
</script>


Output: 

1 2 1 1

 

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



Last Updated : 10 Jun, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads