Given an array A[] of length N, where N is an even number, the task is to answer Q independent queries where each query consists of a positive integer K representing the number of circular shifts performed on the array and find the sum of elements by performing Bitwise OR operation on the divided array.
Note: Each query begins with the original array.
Examples:
Input: A[] = {12, 23, 4, 21, 22, 76}, Q = 1, K = 2
Output: 117
Explanation:
Since K is 2, modified array A[]={22, 76, 12, 23, 4, 21}.
Bitwise OR of first half of array = (22 | 76 | 12) = 94
Bitwise OR of second half of array = (21 | 23 | 4) = 23
Sum of OR values is 94 + 23 = 117
Input: A[] = {7, 44, 19, 86, 65, 39, 75, 101}, Q = 1, K = 4
Output: 238
Since K is 4, modified array A[]={65, 39, 75, 101, 7, 44, 19, 86}.
Bitwise OR of first half of array = 111
Bitwise OR of second half of array = 127
Sum of OR values is 111 + 127 = 238
Naive Approach:
To solve the problem mentioned above the simplest approach is to shift each element of the array by K % (N / 2) and then traverse the array to calculate the OR of the two halves for every query. But this method is not efficient and hence can be optimized further.
Efficient Approach:
To optimize the above mentioned approach we can take the help of Segment Tree data structure.
Observation:
- We can observe that after exactly N / 2 right circular shifts the two halves of the array become the same as in the original array. This effectively reduces the number of rotations to K % (N / 2).
- Performing a right circular shift is basically shifting the last element of the array to the front. So for any positive integer X performing X right circular shifts is equal to shifting the last X elements of the array to the front.
Following are the steps to solve the problem :
- Construct a segment tree for the original array A[] and assign a variable let’s say i = K % (N / 2).
- Then for each query we use the segment tree of find the bitwise OR; that is Bitwise OR of i elements from the end OR bitwise OR of the first (N / 2) – i – 1 elements.
- Then calculate the bitwise OR of elements in range [(N / 2) – i, N – i – 1].
- Add the two results to get the answer for the ith query.
Below is the implementation of the above approach:
// Java program to find Bitwise OR of two // equal halves of an array after performing // K right circular shifts import java.util.*;
class GFG{
static int MAX = 100005 ;
// Array for storing // the segment tree static int []seg = new int [ 4 * MAX];
// Function to build the segment tree static void build( int node, int l,
int r, int a[])
{ if (l == r)
seg[node] = a[l];
else
{
int mid = (l + r) / 2 ;
build( 2 * node, l, mid, a);
build( 2 * node + 1 , mid + 1 , r, a);
seg[node] = (seg[ 2 * node] |
seg[ 2 * node + 1 ]);
}
} // Function to return the OR // of elements in the range [l, r] static int query( int node, int l, int r,
int start, int end, int a[])
{ // Check for out of bound condition
if (l > end || r < start)
return 0 ;
if (start <= l && r <= end)
return seg[node];
// Find middle of the range
int mid = (l + r) / 2 ;
// Recurse for all the elements in array
return ((query( 2 * node, l, mid,
start, end, a)) |
(query( 2 * node + 1 , mid + 1 ,
r, start, end, a)));
} // Function to find the OR sum static void orsum( int a[], int n,
int q, int k[])
{ // Function to build the segment Tree
build( 1 , 0 , n - 1 , a);
// Loop to handle q queries
for ( int j = 0 ; j < q; j++)
{
// Effective number of
// right circular shifts
int i = k[j] % (n / 2 );
// Calculating the OR of
// the two halves of the
// array from the segment tree
// OR of second half of the
// array [n/2-i, n-1-i]
int sec = query( 1 , 0 , n - 1 ,
n / 2 - i,
n - i - 1 , a);
// OR of first half of the array
// [n-i, n-1]OR[0, n/2-1-i]
int first = (query( 1 , 0 , n - 1 , 0 ,
n / 2 - 1 - i, a) |
query( 1 , 0 , n - 1 ,
n - i, n - 1 , a));
int temp = sec + first;
// Print final answer to the query
System.out.print(temp + "
"); }
} // Driver Code public static void main(String[] args)
{ int a[] = { 7 , 44 , 19 , 86 , 65 , 39 , 75 , 101 };
int n = a.length;
int q = 2 ;
int k[] = { 4 , 2 };
orsum(a, n, q, k);
} } // This code is contributed by 29AjayKumar |
238 230
Time Complexity: O(N + Q*logN)
Auxiliary Space: O(4*MAX)
Please refer complete article on Find array sum using Bitwise OR after splitting given array in two halves after K circular shifts for more details!