Given an array arr[] and an integer K, the task is to count the number of sub-arrays having bitwise OR ? K.
Examples:
Input: arr[] = { 1, 2, 3 } K = 3
Output: 4
Bitwise OR of sub-arrays:
{ 1 } = 1
{ 1, 2 } = 3
{ 1, 2, 3 } = 3
{ 2 } = 2
{ 2, 3 } = 3
{ 3 } = 3
4 sub-arrays have bitwise OR ? KInput: arr[] = { 3, 4, 5 } K = 6
Output: 2
Naive approach: Run three nested loops. The outermost loop determines the starting of the sub-array. The middle loop determines the ending of the sub-array. The innermost loop traverses the sub-array whose bounds are determined by the outermost and middle loops. For every sub-array, calculate OR and update count = count + 1 if OR is greater than K.
Below is the implementation of the above approach:
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std;
// Function to return the count of required sub-arrays int countSubArrays( const int * arr, int n, int K)
{ int count = 0;
for ( int i = 0; i < n; i++) {
for ( int j = i; j < n; j++) {
int bitwise_or = 0;
// Traverse sub-array [i..j]
for ( int k = i; k <= j; k++) {
bitwise_or = bitwise_or | arr[k];
}
if (bitwise_or >= K)
count++;
}
}
return count;
} // Driver code int main()
{ int arr[] = { 3, 4, 5 };
int n = sizeof (arr) / sizeof (arr[0]);
int k = 6;
cout << countSubArrays(arr, n, k);
return 0;
} |
// Java implementation of the approach import java.util.*;
class solution
{ // Function to return the count of required sub-arrays static int countSubArrays( int arr[], int n, int K)
{ int count = 0 ;
for ( int i = 0 ; i < n; i++) {
for ( int j = i; j < n; j++) {
int bitwise_or = 0 ;
// Traverse sub-array [i..j]
for ( int k = i; k <= j; k++) {
bitwise_or = bitwise_or | arr[k];
}
if (bitwise_or >= K)
count++;
}
}
return count;
} // Driver code public static void main(String args[])
{ int arr[] = { 3 , 4 , 5 };
int n = arr.length;
int k = 6 ;
System.out.println(countSubArrays(arr, n, k));
} } // This code is contributed by // Surendra_Gangwar |
# Python3 implementation of the approach # Function to return the count of # required sub-arrays def countSubArrays(arr, n, K) :
count = 0 ;
for i in range (n) :
for j in range (i, n) :
bitwise_or = 0
# Traverse sub-array [i..j]
for k in range (i, j + 1 ) :
bitwise_or = bitwise_or | arr[k]
if (bitwise_or > = K) :
count + = 1
return count
# Driver code if __name__ = = "__main__" :
arr = [ 3 , 4 , 5 ]
n = len (arr)
k = 6
print (countSubArrays(arr, n, k))
# This code is contributed by Ryuga |
// C# implementation of the approach using System;
class GFG
{ // Function to return the count of // required sub-arrays static int countSubArrays( int []arr,
int n, int K)
{ int count = 0;
for ( int i = 0; i < n; i++)
{
for ( int j = i; j < n; j++)
{
int bitwise_or = 0;
// Traverse sub-array [i..j]
for ( int k = i; k <= j; k++)
{
bitwise_or = bitwise_or | arr[k];
}
if (bitwise_or >= K)
count++;
}
}
return count;
} // Driver code public static void Main()
{ int []arr = { 3, 4, 5 };
int n = arr.Length;
int k = 6;
Console.WriteLine(countSubArrays(arr, n, k));
} } // This code is contributed by // Mohit kumar |
<?php // PHP implementation of the approach // Function to return the count of // required sub-arrays function countSubArrays( $arr , $n , $K )
{ $count = 0;
for ( $i = 0; $i < $n ; $i ++)
{
for ( $j = 0; $j < $n ; $j ++)
{
$bitwise_or = 0;
// Traverse sub-array [i..j]
for ( $k = $i ; $k < $j + 1; $k ++)
$bitwise_or = $bitwise_or | $arr [ $k ];
if ( $bitwise_or >= $K )
$count += 1;
}
}
return $count ;
} // Driver code $arr = array ( 3, 4, 5 );
$n = count ( $arr );
$k = 6;
print (countSubArrays( $arr , $n , $k ));
// This code is contributed by mits ?> |
<script> // Javascript implementation of the approach
// Function to return the count of required sub-arrays
function countSubArrays(arr, n, K)
{
let count = 0;
for (let i = 0; i < n; i++) {
for (let j = i; j < n; j++) {
let bitwise_or = 0;
// Traverse sub-array [i..j]
for (let k = i; k <= j; k++) {
bitwise_or = bitwise_or | arr[k];
}
if (bitwise_or >= K)
count++;
}
}
return count;
}
// Driver code
let arr = [ 3, 4, 5 ];
let n = arr.length;
let k = 6;
document.write(countSubArrays(arr, n, k));
// This code is contributed by suresh07.
</script> |
2
The time complexity of the above solution is O(n3) and Auxiliary Space is O(1).
An efficient solution uses segment trees to calculate bitwise OR of a sub-array in O(log n) time. Hence, now we directly query the segment tree instead of traversing the sub-array.
Below is the implementation of the above approach:
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std;
#define N 100002 int tree[4 * N];
// Function to build the segment tree void build( int * arr, int node, int start, int end)
{ if (start == end) {
tree[node] = arr[start];
return ;
}
int mid = (start + end) >> 1;
build(arr, 2 * node, start, mid);
build(arr, 2 * node + 1, mid + 1, end);
tree[node] = tree[2 * node] | tree[2 * node + 1];
} // Function to return the bitwise OR of segment [L..R] int query( int node, int start, int end, int l, int r)
{ if (start > end || start > r || end < l) {
return 0;
}
if (start >= l && end <= r) {
return tree[node];
}
int mid = (start + end) >> 1;
int q1 = query(2 * node, start, mid, l, r);
int q2 = query(2 * node + 1, mid + 1, end, l, r);
return q1 | q2;
} // Function to return the count of required sub-arrays int countSubArrays( int arr[], int n, int K)
{ // Build segment tree
build(arr, 1, 0, n - 1);
int count = 0;
for ( int i = 0; i < n; i++) {
for ( int j = i; j < n; j++) {
// Query segment tree for bitwise OR
// of sub-array [i..j]
int bitwise_or = query(1, 0, n - 1, i, j);
if (bitwise_or >= K)
count++;
}
}
return count;
} // Driver code int main()
{ int arr[] = { 3, 4, 5 };
int n = sizeof (arr) / sizeof (arr[0]);
int k = 6;
cout << countSubArrays(arr, n, k);
return 0;
} |
// Java implementation of the approach public class Main
{ static int N = 100002 ;
static int tree[] = new int [ 4 * N];
// Function to build the segment tree
static void build( int arr[], int node,
int start, int end)
{
if (start == end) {
tree[node] = arr[start];
return ;
}
int mid = (start + end) >> 1 ;
build(arr, 2 * node, start, mid);
build(arr, 2 * node + 1 , mid + 1 , end);
tree[node] = tree[ 2 * node] | tree[ 2 * node + 1 ];
}
// Function to return the bitwise OR of segment [L..R]
static int query( int node, int start,
int end, int l, int r)
{
if (start > end || start > r || end < l)
{
return 0 ;
}
if (start >= l && end <= r)
{
return tree[node];
}
int mid = (start + end) >> 1 ;
int q1 = query( 2 * node, start, mid, l, r);
int q2 = query( 2 * node + 1 , mid + 1 , end, l, r);
return q1 | q2;
}
// Function to return the count of required sub-arrays
static int countSubArrays( int arr[], int n, int K)
{
// Build segment tree
build(arr, 1 , 0 , n - 1 );
int count = 0 ;
for ( int i = 0 ; i < n; i++)
{
for ( int j = i; j < n; j++)
{
// Query segment tree for bitwise OR
// of sub-array [i..j]
int bitwise_or = query( 1 , 0 , n - 1 , i, j);
if (bitwise_or >= K)
count++;
}
}
return count;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 3 , 4 , 5 };
int n = arr.length;
int k = 6 ;
System.out.print(countSubArrays(arr, n, k));
}
} // This code is contributed by divyesh072019 |
# Python implementation of the approach N = 100002
tree = [ 0 ] * ( 4 * N)
# Function to build the segment tree def build(arr, node, start, end):
if start = = end:
tree[node] = arr[start]
return
mid = (start + end) >> 1
build(arr, 2 * node, start, mid)
build(arr, 2 * node + 1 , mid + 1 , end)
tree[node] = tree[ 2 * node] | tree[ 2 * node + 1 ]
# Function to return the bitwise OR of segment[L..R] def query(node, start, end, l, r):
if start > end or start > r or end < l:
return 0
if start > = l and end < = r:
return tree[node]
mid = (start + end) >> 1
q1 = query( 2 * node, start, mid, l, r)
q2 = query( 2 * node + 1 , mid + 1 , end, l, r)
return q1 or q2
# Function to return the count of required sub-arrays def countSubArrays(arr, n, K):
# Build segment tree
build(arr, 1 , 0 , n - 1 )
count = 0
for i in range (n):
for j in range (n):
# Query segment tree for bitwise OR
# of sub-array[i..j]
bitwise_or = query( 1 , 0 , n - 1 , i, j)
if bitwise_or > = K:
count + = 1
return count
# Driver code arr = [ 3 , 4 , 5 ]
n = len (arr)
k = 6
print (countSubArrays(arr, n, k))
# This code is contributed by ankush_953 |
// C# implementation of the approach using System;
class GFG {
static int N = 100002;
static int [] tree = new int [4 * N];
// Function to build the segment tree
static void build( int [] arr, int node,
int start, int end)
{
if (start == end) {
tree[node] = arr[start];
return ;
}
int mid = (start + end) >> 1;
build(arr, 2 * node, start, mid);
build(arr, 2 * node + 1, mid + 1, end);
tree[node] = tree[2 * node] | tree[2 * node + 1];
}
// Function to return the bitwise OR of segment [L..R]
static int query( int node, int start,
int end, int l, int r)
{
if (start > end || start > r || end < l)
{
return 0;
}
if (start >= l && end <= r)
{
return tree[node];
}
int mid = (start + end) >> 1;
int q1 = query(2 * node, start, mid, l, r);
int q2 = query(2 * node + 1, mid + 1, end, l, r);
return q1 | q2;
}
// Function to return the count of required sub-arrays
static int countSubArrays( int [] arr, int n, int K)
{
// Build segment tree
build(arr, 1, 0, n - 1);
int count = 0;
for ( int i = 0; i < n; i++)
{
for ( int j = i; j < n; j++)
{
// Query segment tree for bitwise OR
// of sub-array [i..j]
int bitwise_or = query(1, 0, n - 1, i, j);
if (bitwise_or >= K)
count++;
}
}
return count;
}
// Driver code
static void Main() {
int [] arr = { 3, 4, 5 };
int n = arr.Length;
int k = 6;
Console.WriteLine(countSubArrays(arr, n, k));
}
} // This code is contributed by divyeshrabadiya07. |
<script> // Javascript implementation of the approach let N = 100002; let tree = new Array(4 * N);
// Function to build the segment tree function build(arr, node, start, end)
{ if (start == end)
{
tree[node] = arr[start];
return ;
}
let mid = (start + end) >> 1;
build(arr, 2 * node, start, mid);
build(arr, 2 * node + 1, mid + 1, end);
tree[node] = tree[2 * node] | tree[2 * node + 1];
} // Function to return the bitwise OR of segment [L..R] function query(node, start, end, l, r)
{ if (start > end || start > r || end < l)
{
return 0;
}
if (start >= l && end <= r)
{
return tree[node];
}
let mid = (start + end) >> 1;
let q1 = query(2 * node, start, mid, l, r);
let q2 = query(2 * node + 1, mid + 1, end, l, r);
return q1 | q2;
} // Function to return the count of // required sub-arrays function countSubArrays(arr, n, K)
{ // Build segment tree
build(arr, 1, 0, n - 1);
let count = 0;
for (let i = 0; i < n; i++)
{
for (let j = i; j < n; j++)
{
// Query segment tree for bitwise OR
// of sub-array [i..j]
let bitwise_or = query(1, 0, n - 1, i, j);
if (bitwise_or >= K)
count++;
}
}
return count;
} // Driver code let arr = [ 3, 4, 5 ]; let n = arr.length; let k = 6; document.write(countSubArrays(arr, n, k)); // This code is contributed by rag2127 </script> |
2
Complexity Analysis:
- Time complexity: O(n2 log n).
- Auxiliary Space: O(n).
A further efficient solution uses binary search. Bitwise OR is a function that never decreases with the number of inputs. For example:
OR(a, b) ? OR(a, b, c)
OR(a1, a2, a3, …) ? OR(a1, a2, a3, …, b)
By this property, OR(ai, …, aj) <= OR(ai, …, aj, aj+1). Hence, if OR(ai, …, aj) is greater than K then OR(ai, …, aj, aj+1) will also be greater than K. Hence, once we find a subarray [i..j] whose OR is greater than K, we don’t need to check subarrays [i..j+1], [i..j+2], .. and so on, because their OR will also be greater than K. We can add the count of remaining subarrays to the current sum. The first subarray from a particular starting point whose OR is greater than K is found using binary search.
Below is the implementation of the above idea:
// C++ program to implement the above approach #include <bits/stdc++.h> #define N 100002 using namespace std;
int tree[4 * N];
// Function which builds the segment tree void build( int * arr, int node, int start, int end)
{ if (start == end) {
tree[node] = arr[start];
return ;
}
int mid = (start + end) >> 1;
build(arr, 2 * node, start, mid);
build(arr, 2 * node + 1, mid + 1, end);
tree[node] = tree[2 * node] | tree[2 * node + 1];
} // Function that returns bitwise OR of segment [L..R] int query( int node, int start, int end, int l, int r)
{ if (start > end || start > r || end < l) {
return 0;
}
if (start >= l && end <= r) {
return tree[node];
}
int mid = (start + end) >> 1;
int q1 = query(2 * node, start, mid, l, r);
int q2 = query(2 * node + 1, mid + 1, end, l, r);
return q1 | q2;
} // Function to count requisite number of subarrays int countSubArrays( const int * arr, int n, int K)
{ int count = 0;
for ( int i = 0; i < n; i++) {
// Check for subarrays starting with index i
int low = i, high = n - 1, index = INT_MAX;
while (low <= high) {
int mid = (low + high) >> 1;
// If OR of subarray [i..mid] >= K,
// then all subsequent subarrays will have OR >= K
// therefore reduce high to mid - 1
// to find the minimal length subarray
// [i..mid] having OR >= K
if (query(1, 0, n - 1, i, mid) >= K) {
index = min(index, mid);
high = mid - 1;
}
else {
low = mid + 1;
}
}
// Increase count with number of subarrays
// having OR >= K and starting with index i
if (index != INT_MAX) {
count += n - index;
}
}
return count;
} // Driver code int main()
{ int arr[] = { 3, 4, 5 };
int n = sizeof (arr) / sizeof (arr[0]);
// Build segment tree.
build(arr, 1, 0, n - 1);
int k = 6;
cout << countSubArrays(arr, n, k);
return 0;
} |
// Java implementation of the above approach class GFG
{ static int N = 100002 ;
static int tree[] = new int [ 4 * N];
// Function which builds the segment tree
static void build( int [] arr, int node,
int start, int end)
{
if (start == end)
{
tree[node] = arr[start];
return ;
}
int mid = (start + end) >> 1 ;
build(arr, 2 * node, start, mid);
build(arr, 2 * node + 1 , mid + 1 , end);
tree[node] = tree[ 2 * node] | tree[ 2 * node + 1 ];
}
// Function that returns bitwise
// OR of segment [L..R]
static int query( int node, int start,
int end, int l, int r)
{
if (start > end || start > r || end < l)
{
return 0 ;
}
if (start >= l && end <= r)
{
return tree[node];
}
int mid = (start + end) >> 1 ;
int q1 = query( 2 * node, start, mid, l, r);
int q2 = query( 2 * node + 1 , mid + 1 , end, l, r);
return q1 | q2;
}
// Function to count requisite number of subarrays
static int countSubArrays( int [] arr,
int n, int K)
{
int count = 0 ;
for ( int i = 0 ; i < n; i++)
{
// Check for subarrays starting with index i
int low = i, high = n - 1 , index = Integer.MAX_VALUE;
while (low <= high)
{
int mid = (low + high) >> 1 ;
// If OR of subarray [i..mid] >= K,
// then all subsequent subarrays will
// have OR >= K therefore reduce
// high to mid - 1 to find the
// minimal length subarray
// [i..mid] having OR >= K
if (query( 1 , 0 , n - 1 , i, mid) >= K)
{
index = Math.min(index, mid);
high = mid - 1 ;
}
else
{
low = mid + 1 ;
}
}
// Increase count with number of subarrays
// having OR >= K and starting with index i
if (index != Integer.MAX_VALUE)
{
count += n - index;
}
}
return count;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 3 , 4 , 5 };
int n = arr.length;
// Build segment tree.
build(arr, 1 , 0 , n - 1 );
int k = 6 ;
System.out.println(countSubArrays(arr, n, k));
}
} // This code is contributed by Rajput-Ji |
# Python3 program to implement the above approach N = 100002
tree = [ 0 for i in range ( 4 * N)];
# Function which builds the segment tree def build(arr, node, start, end):
if (start = = end):
tree[node] = arr[start];
return ;
mid = (start + end) >> 1 ;
build(arr, 2 * node, start, mid);
build(arr, 2 * node + 1 , mid + 1 , end);
tree[node] = tree[ 2 * node] | tree[ 2 * node + 1 ];
# Function that returns bitwise OR of segment [L..R] def query(node, start, end, l, r):
if (start > end or start > r or end < l):
return 0 ;
if (start > = l and end < = r):
return tree[node];
mid = (start + end) >> 1 ;
q1 = query( 2 * node, start, mid, l, r);
q2 = query( 2 * node + 1 , mid + 1 , end, l, r);
return q1 | q2;
# Function to count requisite number of subarrays def countSubArrays(arr, n, K):
count = 0 ;
for i in range (n):
# Check for subarrays starting with index i
low = i
high = n - 1
index = 1000000000
while (low < = high):
mid = (low + high) >> 1 ;
# If OR of subarray [i..mid] >= K,
# then all subsequent subarrays will have OR >= K
# therefore reduce high to mid - 1
# to find the minimal length subarray
# [i..mid] having OR >= K
if (query( 1 , 0 , n - 1 , i, mid) > = K):
index = min (index, mid);
high = mid - 1 ;
else :
low = mid + 1 ;
# Increase count with number of subarrays
# having OR >= K and starting with index i
if (index ! = 1000000000 ):
count + = n - index;
return count;
# Driver code if __name__ = = '__main__' :
arr = [ 3 , 4 , 5 ]
n = len (arr)
# Build segment tree.
build(arr, 1 , 0 , n - 1 );
k = 6 ;
print (countSubArrays(arr, n, k))
# This code is contributed by rutvik_56. |
// C# implementation of the above approach using System;
class GFG
{ static int N = 100002;
static int []tree = new int [4 * N];
// Function which builds the segment tree
static void build( int [] arr, int node,
int start, int end)
{
if (start == end)
{
tree[node] = arr[start];
return ;
}
int mid = (start + end) >> 1;
build(arr, 2 * node, start, mid);
build(arr, 2 * node + 1, mid + 1, end);
tree[node] = tree[2 * node] | tree[2 * node + 1];
}
// Function that returns bitwise
// OR of segment [L..R]
static int query( int node, int start,
int end, int l, int r)
{
if (start > end || start > r || end < l)
{
return 0;
}
if (start >= l && end <= r)
{
return tree[node];
}
int mid = (start + end) >> 1;
int q1 = query(2 * node, start, mid, l, r);
int q2 = query(2 * node + 1, mid + 1, end, l, r);
return q1 | q2;
}
// Function to count requisite number of subarrays
static int countSubArrays( int [] arr,
int n, int K)
{
int count = 0;
for ( int i = 0; i < n; i++)
{
// Check for subarrays starting with index i
int low = i, high = n - 1, index = int .MaxValue;
while (low <= high)
{
int mid = (low + high) >> 1;
// If OR of subarray [i..mid] >= K,
// then all subsequent subarrays will
// have OR >= K therefore reduce
// high to mid - 1 to find the
// minimal length subarray
// [i..mid] having OR >= K
if (query(1, 0, n - 1, i, mid) >= K)
{
index = Math.Min(index, mid);
high = mid - 1;
}
else
{
low = mid + 1;
}
}
// Increase count with number of subarrays
// having OR >= K and starting with index i
if (index != int .MaxValue)
{
count += n - index;
}
}
return count;
}
// Driver code
public static void Main(String[] args)
{
int []arr = {3, 4, 5};
int n = arr.Length;
// Build segment tree.
build(arr, 1, 0, n - 1);
int k = 6;
Console.WriteLine(countSubArrays(arr, n, k));
}
} // This code is contributed by PrinciRaj1992 |
<script> // JavaScript implementation of the above approach let N = 100002;
let tree= new Array(4*N);
// Function which builds the segment tree
function build(arr,node,start,end)
{
if (start == end)
{
tree[node] = arr[start];
return ;
}
let mid = (start + end) >> 1;
build(arr, 2 * node, start, mid);
build(arr, 2 * node + 1, mid + 1, end);
tree[node] = tree[2 * node] | tree[2 * node + 1];
}
// Function that returns bitwise
// OR of segment [L..R]
function query(node,start,end,l,r)
{
if (start > end || start > r || end < l)
{
return 0;
}
if (start >= l && end <= r)
{
return tree[node];
}
let mid = (start + end) >> 1;
let q1 = query(2 * node, start, mid, l, r);
let q2 = query(2 * node + 1, mid + 1, end, l, r);
return q1 | q2;
}
// Function to count requisite number of subarrays
function countSubArrays(arr,n,K)
{
let count = 0;
for (let i = 0; i < n; i++)
{
// Check for subarrays starting with index i
let low = i, high = n - 1, index = Number.MAX_VALUE;
while (low <= high)
{
let mid = (low + high) >> 1;
// If OR of subarray [i..mid] >= K,
// then all subsequent subarrays will
// have OR >= K therefore reduce
// high to mid - 1 to find the
// minimal length subarray
// [i..mid] having OR >= K
if (query(1, 0, n - 1, i, mid) >= K)
{
index = Math.min(index, mid);
high = mid - 1;
}
else
{
low = mid + 1;
}
}
// Increase count with number of subarrays
// having OR >= K and starting with index i
if (index != Number.MAX_VALUE)
{
count += n - index;
}
}
return count;
}
// Driver code
let arr=[3, 4, 5];
let n = arr.length;
// Build segment tree.
build(arr, 1, 0, n - 1);
let k = 6;
document.write(countSubArrays(arr, n, k));
// This code is contributed by patel2127 </script> |
2
Complexity Analysis:
- Time complexity: O(n log2 n).
- Auxiliary Space: O(n).