Open In App

Queries for bitwise OR in the given matrix

Last Updated : 24 Nov, 2021
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an N * N matrix mat[][] consisting of non-negative integers and some queries consisting of top-left and bottom-right corner of the sub-matrix, the task is to find the bit-wise OR of all the elements of the sub-matrix given in each query.
Examples: 
 

Input: mat[][] = { 
{1, 2, 3}, 
{4, 5, 6}, 
{7, 8, 9}}, 
q[] = {{1, 1, 1, 1}, {1, 2, 2, 2}} 
Output: 

15 
Query 1: Only element in the sub-matrix is 5. 
Query 2: 6 OR 9 = 15
Input: mat[][] = { 
{12, 23, 13}, 
{41, 15, 46}, 
{75, 82, 123}}, 
q[] = {{0, 0, 2, 2}, {1, 1, 2, 1}} 
Output: 
127 
95 
 


 


Naive approach: Iterate through the sub-matrix and find the bit-wise OR of all the numbers in that range. This will take O(n2) time for each query in the worst case.
Efficient approach: If we look at the integers as a binary number, we can easily see that condition for ith bit of our answer to be set is that ith bit of at least one integer in the sub-matrix is set. 
So, we will calculate the prefix count for each bit. We will use this to find the number of integers in the sub-matrix with ith bit set. If it is non-zero then the ith bit of our answer will also be set. 
For this, we will create a 3d-array, prefix_count[][][] where prefix_count[i][x][y] will store the count of all the elements of the sub-matrix with top left corner at {0, 0} and bottom right corner at {x, y} and ith bit set. Refer 
this article to understand prefix_count in case of matrix.
Below is the implementation of the above approach: 
 

C++
// C++ implementation of the approach
#include <bits/stdc++.h>
#define bitscount 32
#define n 3
using namespace std;

// Array to store bit-wise
// prefix count
int prefix_count[bitscount][n][n];

// Function to find the prefix sum
void findPrefixCount(int arr[][n])
{

    // Loop for each bit
    for (int i = 0; i < bitscount; i++) {

        // Loop to find prefix-count
        // for each row
        for (int j = 0; j < n; j++) {
            prefix_count[i][j][0] = ((arr[j][0] >> i) & 1);
            for (int k = 1; k < n; k++) {
                prefix_count[i][j][k] = ((arr[j][k] >> i) & 1);
                prefix_count[i][j][k] += prefix_count[i][j][k - 1];
            }
        }
    }

    // Finding column-wise prefix
    // count
    for (int i = 0; i < bitscount; i++)
        for (int j = 1; j < n; j++)
            for (int k = 0; k < n; k++)
                prefix_count[i][j][k] += prefix_count[i][j - 1][k];
}

// Function to return the result for a query
int rangeOr(int x1, int y1, int x2, int y2)
{

    // To store the answer
    int ans = 0;

    // Loop for each bit
    for (int i = 0; i < bitscount; i++) {

        // To store the number of variables
        // with ith bit set
        int p;
        if (x1 == 0 and y1 == 0)
            p = prefix_count[i][x2][y2];
        else if (x1 == 0)
            p = prefix_count[i][x2][y2]
                - prefix_count[i][x2][y1 - 1];
        else if (y1 == 0)
            p = prefix_count[i][x2][y2]
                - prefix_count[i][x1 - 1][y2];
        else
            p = prefix_count[i][x2][y2]
                - prefix_count[i][x1 - 1][y2]
                - prefix_count[i][x2][y1 - 1]
                + prefix_count[i][x1 - 1][y1 - 1];

        // If count of variables with ith bit
        // set is greater than 0
        if (p != 0)
            ans = (ans | (1 << i));
    }

    return ans;
}

// Driver code
int main()
{
    int arr[][n] = { { 1, 2, 3 },
                     { 4, 5, 6 },
                     { 7, 8, 9 } };

    findPrefixCount(arr);

    int queries[][4] = { { 1, 1, 1, 1 }, { 1, 2, 2, 2 } };
    int q = sizeof(queries) / sizeof(queries[0]);

    for (int i = 0; i < q; i++)
        cout << rangeOr(queries[i][0],
                        queries[i][1],
                        queries[i][2],
                        queries[i][3])
             << endl;

    return 0;
}
Java
// Java implementation of the approach 

class GFG
{

    final static int bitscount = 32 ;
    final static int n = 3 ;

    // Array to store bit-wise 
    // prefix count 
    static int prefix_count[][][] = new int [bitscount][n][n]; 
    
    // Function to find the prefix sum 
    static void findPrefixCount(int arr[][]) 
    { 
    
        // Loop for each bit 
        for (int i = 0; i < bitscount; i++)
        { 
    
            // Loop to find prefix-count 
            // for each row 
            for (int j = 0; j < n; j++)
            { 
                prefix_count[i][j][0] = ((arr[j][0] >> i) & 1); 
                for (int k = 1; k < n; k++)
                { 
                    prefix_count[i][j][k] = ((arr[j][k] >> i) & 1); 
                    prefix_count[i][j][k] += prefix_count[i][j][k - 1]; 
                } 
            } 
        } 
    
        // Finding column-wise prefix 
        // count 
        for (int i = 0; i < bitscount; i++) 
            for (int j = 1; j < n; j++) 
                for (int k = 0; k < n; k++) 
                    prefix_count[i][j][k] += prefix_count[i][j - 1][k]; 
    } 
    
    // Function to return the result for a query 
    static int rangeOr(int x1, int y1, int x2, int y2) 
    { 
    
        // To store the answer 
        int ans = 0; 
    
        // Loop for each bit 
        for (int i = 0; i < bitscount; i++) 
        { 
    
            // To store the number of variables 
            // with ith bit set 
            int p; 
            if (x1 == 0 && y1 == 0) 
                p = prefix_count[i][x2][y2]; 
            else if (x1 == 0) 
                p = prefix_count[i][x2][y2] 
                    - prefix_count[i][x2][y1 - 1]; 
            else if (y1 == 0) 
                p = prefix_count[i][x2][y2] 
                    - prefix_count[i][x1 - 1][y2]; 
            else
                p = prefix_count[i][x2][y2] 
                    - prefix_count[i][x1 - 1][y2] 
                    - prefix_count[i][x2][y1 - 1] 
                    + prefix_count[i][x1 - 1][y1 - 1]; 
    
            // If count of variables with ith bit 
            // set is greater than 0 
            if (p != 0) 
                ans = (ans | (1 << i)); 
        } 
    
        return ans; 
    } 
    
    // Driver code 
    public static void main (String[] args) 
    {
        int arr[][] = { { 1, 2, 3 }, 
                        { 4, 5, 6 }, 
                        { 7, 8, 9 } }; 
    
        findPrefixCount(arr); 
    
        int queries[][] = { { 1, 1, 1, 1 }, { 1, 2, 2, 2 } }; 
        int q = queries.length; 
    
        for (int i = 0; i < q; i++) 
            System.out.println( rangeOr(queries[i][0], 
                            queries[i][1], 
                            queries[i][2], 
                            queries[i][3]) );
    }
}

// This code is contributed by AnkitRai
Python3
# Python 3 implementation of the approach
bitscount = 32
n = 3
# Array to store bit-wise
# prefix count
prefix_count = [[[0 for i in range(n)] for j in range(n)] for k in range(bitscount)]

# Function to find the prefix sum
def findPrefixCount(arr):
    # Loop for each bit
    for i in range(bitscount):
        # Loop to find prefix-count
        # for each row
        for j in range(n):
            prefix_count[i][j][0] = ((arr[j][0] >> i) & 1)
            for k in range(1,n):
                prefix_count[i][j][k] = ((arr[j][k] >> i) & 1)
                prefix_count[i][j][k] += prefix_count[i][j][k - 1]

    # Finding column-wise prefix
    # count
    for i in range(bitscount):
        for j in range(1,n):
            for k in range(n):
                prefix_count[i][j][k] += prefix_count[i][j - 1][k]

# Function to return the result for a query
def rangeOr(x1, y1, x2, y2):
    # To store the answer
    ans = 0

    # Loop for each bit
    for i in range(bitscount):
        # To store the number of variables
        # with ith bit set
        if (x1 == 0 and y1 == 0):
            p = prefix_count[i][x2][y2]
        elif (x1 == 0):
            p = prefix_count[i][x2][y2] - prefix_count[i][x2][y1 - 1]
        elif (y1 == 0):
            p = prefix_count[i][x2][y2] - prefix_count[i][x1 - 1][y2]
        else:
            p = prefix_count[i][x2][y2] - prefix_count[i][x1 - 1][y2] - prefix_count[i][x2][y1 - 1] + prefix_count[i][x1 - 1][y1 - 1];

        # If count of variables with ith bit
        # set is greater than 0
        if (p != 0):
            ans = (ans | (1 << i))

    return ans

# Driver code
if __name__ == '__main__':
    arr =  [[1, 2, 3],
            [4, 5, 6],
            [7, 8, 9]]

    findPrefixCount(arr)
    queries = [[1, 1, 1, 1],
                        [1, 2, 2, 2]]
    q = len(queries)

    for i in range(q):
        print(rangeOr(queries[i][0],queries[i][1],queries[i][2],queries[i][3]))
        
# This code is contributed by
# Surendra_Gangwar
C#
// C# implementation of the approach
using System;
    
class GFG
{

    static int bitscount = 32 ;
    static int n = 3 ;

    // Array to store bit-wise 
    // prefix count 
    static int [,,]prefix_count = new int [bitscount,n,n]; 
    
    // Function to find the prefix sum 
    static void findPrefixCount(int [,]arr) 
    { 
    
        // Loop for each bit 
        for (int i = 0; i < bitscount; i++)
        { 
    
            // Loop to find prefix-count 
            // for each row 
            for (int j = 0; j < n; j++)
            { 
                prefix_count[i,j,0] = ((arr[j,0] >> i) & 1); 
                for (int k = 1; k < n; k++)
                { 
                    prefix_count[i, j, k] = ((arr[j, k] >> i) & 1); 
                    prefix_count[i, j, k] += prefix_count[i, j, k - 1]; 
                } 
            } 
        } 
    
        // Finding column-wise prefix 
        // count 
        for (int i = 0; i < bitscount; i++) 
            for (int j = 1; j < n; j++) 
                for (int k = 0; k < n; k++) 
                    prefix_count[i, j, k] += prefix_count[i, j - 1, k]; 
    } 
    
    // Function to return the result for a query 
    static int rangeOr(int x1, int y1, int x2, int y2) 
    { 
    
        // To store the answer 
        int ans = 0; 
    
        // Loop for each bit 
        for (int i = 0; i < bitscount; i++) 
        { 
    
            // To store the number of variables 
            // with ith bit set 
            int p; 
            if (x1 == 0 && y1 == 0) 
                p = prefix_count[i, x2, y2]; 
            else if (x1 == 0) 
                p = prefix_count[i, x2, y2] 
                    - prefix_count[i, x2, y1 - 1]; 
            else if (y1 == 0) 
                p = prefix_count[i, x2, y2] 
                    - prefix_count[i, x1 - 1, y2]; 
            else
                p = prefix_count[i, x2, y2] 
                    - prefix_count[i, x1 - 1, y2] 
                    - prefix_count[i, x2, y1 - 1] 
                    + prefix_count[i, x1 - 1, y1 - 1]; 
    
            // If count of variables with ith bit 
            // set is greater than 0 
            if (p != 0) 
                ans = (ans | (1 << i)); 
        } 
    
        return ans; 
    } 
    
    // Driver code 
    public static void Main (String[] args) 
    {
        int [,]arr = { { 1, 2, 3 }, 
                        { 4, 5, 6 }, 
                        { 7, 8, 9 } }; 
    
        findPrefixCount(arr); 
    
        int [,]queries = { { 1, 1, 1, 1 }, { 1, 2, 2, 2 } }; 
        int q = queries.GetLength(0); 
    
        for (int i = 0; i < q; i++) 
            Console.WriteLine( rangeOr(queries[i,0], 
                            queries[i,1], 
                            queries[i,2], 
                            queries[i,3]) );
    }
}

/* This code contributed by PrinciRaj1992 */
JavaScript
<script>

// Javascript implementation of the approach

const bitscount = 32;
const n = 3;

// Array to store bit-wise
// prefix count
let prefix_count = new Array(bitscount);
for (let i = 0; i < bitscount; i++) {
    prefix_count[i] = new Array(n);
    for (let j = 0; j < n; j++)
        prefix_count[i][j] = new Array(n);
}

// Function to find the prefix sum
function findPrefixCount(arr)
{

    // Loop for each bit
    for (let i = 0; i < bitscount; i++) 
    {

        // Loop to find prefix-count
        // for each row
        for (let j = 0; j < n; j++) {
            prefix_count[i][j][0] = 
            ((arr[j][0] >> i) & 1);
            for (let k = 1; k < n; k++) 
            {
                prefix_count[i][j][k] = 
                ((arr[j][k] >> i) & 1);
                prefix_count[i][j][k] += 
                prefix_count[i][j][k - 1];
            }
        }
    }

    // Finding column-wise prefix
    // count
    for (let i = 0; i < bitscount; i++)
        for (let j = 1; j < n; j++)
            for (let k = 0; k < n; k++)
                prefix_count[i][j][k] += 
                prefix_count[i][j - 1][k];
}

// Function to return the result for a query
function rangeOr(x1, y1, x2, y2)
{

    // To store the answer
    let ans = 0;

    // Loop for each bit
    for (let i = 0; i < bitscount; i++) {

        // To store the number of variables
        // with ith bit set
        let p;
        if (x1 == 0 && y1 == 0)
            p = prefix_count[i][x2][y2];
        else if (x1 == 0)
            p = prefix_count[i][x2][y2]
                - prefix_count[i][x2][y1 - 1];
        else if (y1 == 0)
            p = prefix_count[i][x2][y2]
                - prefix_count[i][x1 - 1][y2];
        else
            p = prefix_count[i][x2][y2]
                - prefix_count[i][x1 - 1][y2]
                - prefix_count[i][x2][y1 - 1]
                + prefix_count[i][x1 - 1][y1 - 1];

        // If count of variables with ith bit
        // set is greater than 0
        if (p != 0)
            ans = (ans | (1 << i));
    }

    return ans;
}

// Driver code
    let arr = [ [ 1, 2, 3 ],
                     [ 4, 5, 6 ],
                     [ 7, 8, 9 ] ];

    findPrefixCount(arr);

    let queries = [ [ 1, 1, 1, 1 ], [ 1, 2, 2, 2 ] ];
    let q = queries.length;

    for (let i = 0; i < q; i++)
        document.write(rangeOr(queries[i][0],
                        queries[i][1],
                        queries[i][2],
                        queries[i][3]) + "<br>");

</script>

Output: 
5
15

 

Time complexity for pre-computation is O(n2) and each query can be answered in O(1)

Auxiliary Space: O(n2)
 


Next Article

Similar Reads