📜  子数组的数量按位或> = K

📅  最后修改于: 2021-06-26 22:21:09             🧑  作者: Mango

给定数组arr []和整数K ,任务是计算按位OR≥K的子数组的数量。
例子:

天真的方法:运行三个嵌套循环。最外面的循环确定子数组的开始。中间循环确定子数组的结尾。最内层的循环遍历子数组,其边界由最外层和中间的循环确定。对于每个子数组,计算OR,如果OR大于K ,则更新count = count + 1
下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
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
// 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
# 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#
// 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
= $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
?>


Javascript


C++
// C++ implementation of the approach
#include 
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
// 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


Python3
# 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#
// 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 contributd by divyeshrabadiya07.


C++
// C++ program to implement the above approach
#include 
 
#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
// 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
# 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#
// 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


输出:
2

上述解决方案的时间复杂度为O(n 3 )。
一个有效的解决方案使用段树在O(log n)时间内计算子数组的按位或。因此,现在我们直接查询段树,而不是遍历子数组。
下面是上述方法的实现:

C++

// C++ implementation of the approach
#include 
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

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

Python3

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

// 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 contributd by divyeshrabadiya07.
输出:
2

上述解决方案的时间复杂度为O(n 2 log n)。
一种有效的解决方案是使用二进制搜索。按位或运算是一个永远不会随着输入数量而减少的函数。例如:

通过此属性, OR(a i ,…,a j )<= OR(a i ,…,a j ,a j + 1 ) 。因此,如果OR(a i ,…,a j )大于K,则OR(a i ,…,a jj + 1 )也将大于K。因此,一旦找到子数组[i。 .j]的OR大于K,我们不需要检查子数组[i..j + 1],[i..j + 2],..等等,因为它们的OR也将大于K.我们可以将剩余子数组的计数添加到当前总和中。使用二进制搜索找到从特定起点开始的第一个子数组,该数组的OR大于K。
下面是上述想法的实现:

C++

// C++ program to implement the above approach
#include 
 
#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

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

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

// 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
输出:
2

上述解决方案的时间复杂度为O(n log 2 n)

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。