📜  对于给定的范围查询,使按位与非零的范围内的最小删除

📅  最后修改于: 2022-05-13 01:56:07.211000             🧑  作者: Mango

对于给定的范围查询,使按位与非零的范围内的最小删除

给定一个Q范围查询的数组queries[][] ,任务是从范围[l, r]中找到最小移除,使得范围的按位是非零值。

例子:

朴素的方法:这可以通过遍历每个范围并检查具有公共设置位的范围内元素的最大计数并将其从元素的总计数中删除来解决,即(r – l + 1)

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function the find the minimum removals
// to make the bitwise AND of range non-zero
void solve_queries(vector > q)
{
    for (int i = 0; i < q.size(); i++) {
        int l = q[i][0];
        int r = q[i][1];
 
        // Initialize the max_set to check
        // what count of set bit majority of
        // numbers in the range was set
        int max_set = 0;
        for (int i = 0; i < 31; i++) {
            int cnt = 0;
            for (int j = l; j <= r; j++) {
 
                // Check if is set
                if ((1 << i) & j) {
                    cnt++;
                }
            }
            max_set = max(max_set, cnt);
        }
 
        // Total length of range - count of
        // max numbers having 1 bit set in range
        cout << (r - l + 1) - max_set << " ";
    }
}
 
// Driver Code
int main()
{
    // Initialize the queries
    vector > queries
        = { { 1, 5 }, { 3, 4 }, { 5, 10 }, { 10, 15 } };
 
    solve_queries(queries);
    return 0;
}


Java
// Java code to implement the above approach
import java.util.*;
public class GFG
{
 
  // Function the find the minimum removals
  // to make the bitwise AND of range non-zero
  static void solve_queries(int [][]q)
  {
    for (int i = 0; i < q.length; i++) {
      int l = q[i][0];
      int r = q[i][1];
 
      // Initialize the max_set to check
      // what count of set bit majority of
      // numbers in the range was set
      int max_set = 0;
      for (int k = 0; k < 31; k++) {
        int cnt = 0;
        for (int j = l; j <= r; j++) {
 
          // Check if is set
          if (((1 << k) & j) != 0) {
            cnt++;
          }
        }
        max_set = Math. max(max_set, cnt);
      }
 
      // Total length of range - count of
      // max numbers having 1 bit set in range
      System.out.print((r - l + 1) - max_set + " ");
    }
  }
 
  // Driver code
  public static void main(String args[])
  {
    // Initialize the queries
    int [][]queries
      = { { 1, 5 }, { 3, 4 }, { 5, 10 }, { 10, 15 } };
 
    solve_queries(queries);
  }
}
 
// This code is contributed by Samim Hossain Mondal.


Python3
# Python program for the above approach
 
# Function the find the minimum removals
# to make the bitwise AND of range non-zero
def solve_queries (q):
 
    for i in range(len(q)):
        l = q[i][0]
        r = q[i][1]
 
        # Initialize the max_set to check
        # what count of set bit majority of
        # numbers in the range was set
        max_set = 0
        for i in range(31):
            cnt = 0
            for j in range(l, r + 1):
 
                # Check if is set
                if ((1 << i) & j):
                    cnt += 1
            max_set = max(max_set, cnt)
 
        # Total length of range - count of
        # max numbers having 1 bit set in range
        print(f"{(r - l + 1) - max_set} ", end=" ")
 
# Driver Code
 
# Initialize the queries
queries = [[1, 5], [3, 4], [5, 10], [10, 15]]
 
solve_queries(queries)
 
# This code is contributed by gfgking


C#
// C# code to implement the above approach
using System;
public class GFG{
 
  // Function the find the minimum removals
  // to make the bitwise AND of range non-zero
  static void solve_queries(int[,] q)
  {
    for (int i = 0; i < 4; i++) {
      int l = q[i, 0];
      int r = q[i, 1];
 
      // Initialize the max_set to check
      // what count of set bit majority of
      // numbers in the range was set
      int max_set = 0;
      for (int k = 0; k < 31; k++) {
        int cnt = 0;
        for (int j = l; j <= r; j++) {
 
          // Check if is set
          if (((1 << k) & j) != 0) {
            cnt++;
          }
        }
        max_set = Math.Max(max_set, cnt);
      }
 
      // Total length of range - count of
      // max numbers having 1 bit set in range
      Console.Write((r - l + 1) - max_set + " ");
    }
  }
 
  // Driver code
  static public void Main()
  {
     
    // Initialize the queries
    int[,] queries = new int[4,2] { { 1, 5 }, { 3, 4 }, { 5, 10 }, { 10, 15 } };
 
    solve_queries(queries);
  }
}
 
// This code is contributed by Shubham Singh


Javascript


C++
// C++ program for the above approach
#include 
using namespace std;
 
int dp[200005][31];
 
// Function to build the dp array
// which stores the set bits for
// each bit position till 200005.
void count_set_bits()
{
    int N = 2e5 + 5;
    for (int i = 1; i < N; i++) {
        for (int j = 0; j <= 30; j++) {
            // If j th bit is set assign
            // dp[i][j] =1 where dp[i][j] means
            // number of jth bits set till i
            if (i & (1 << j))
                dp[i][j] = 1;
 
            // Calculate the prefix sum
            dp[i][j] += dp[i - 1][j];
        }
    }
}
 
// Function to solve the queries
void solve_queries(vector > q)
{
    // Call the function to
    // precalculate the dp array
    count_set_bits();
    for (int i = 0; i < q.size(); i++) {
 
        int l = q[i][0];
        int r = q[i][1];
 
        // Initialize the max_set = INT_MIN to
        // check what count of set bit
        // majority of numbers in the range was set
        int max_set = INT_MIN;
 
        // For each bit check the
        // maximum numbers in the range
        // having the j th bit set
        for (int j = 0; j <= 30; j++) {
            int total_set = (dp[r][j] - dp[l - 1][j]);
 
            max_set = max(max_set, total_set);
        }
 
        // Total length of range - count of max
        // numbers having 1 bit set in the range
        cout << (r - l + 1) - max_set << " ";
    }
}
 
// Driver Code
int main()
{
 
    // Initialize the queries
    vector > queries
        = { { 1, 5 }, { 3, 4 }, { 5, 10 }, { 10, 15 } };
 
    solve_queries(queries);
    return 0;
}


Java
// Java code to implement the above approach
import java.io.*;
 
class GFG
{
 
  public static int dp[][] = new int[200005][31];
 
  // Function to build the dp array
  // which stores the set bits for
  // each bit position till 200005.
  public static void count_set_bits()
  {
    int N = 200005;
    for (int i = 1; i < N; i++)
    {
      for (int j = 0; j <= 30; j++)
      {
 
        // If j th bit is set assign
        // dp[i][j] =1 where dp[i][j] means
        // number of jth bits set till i
        if ((i & (1 << j))!=0)
          dp[i][j] = 1;
 
        // Calculate the prefix sum
        dp[i][j] += dp[i - 1][j];
      }
    }
  }
 
  // Function to solv e the queries
  public static void solve_queries(int[][] q)
  {
 
    // Call the function to
    // precalculate the dp array
    count_set_bits();
    for (int i = 0; i < q.length; i++) {
 
      int l = q[i][0];
      int r = q[i][1];
 
      // Initialize the max_set = INT_MIN to
      // check what count of set bit
      // majority of numbers in the range was set
      int max_set = Integer.MIN_VALUE;
 
      // For each bit check the
      // maximum numbers in the range
      // having the j th bit set
      for (int j = 0; j <= 30; j++) {
        int total_set = (dp[r][j] - dp[l - 1][j]);
 
        max_set = Math.max(max_set, total_set);
      }
 
      // Total length of range - count of max
      // numbers having 1 bit set in the range
      System.out.print((r - l + 1) - max_set + " ");
    }
  }
 
  // Driver Code
  public static void main (String[] args)
  {
 
    // Initialize the queries
    int[][] queries = new int[][]
    {
      new int[] { 1, 5 },
      new int[] { 3, 4 },
      new int[] { 5, 10 },
      new int[] { 10, 15 }
    };
 
    solve_queries(queries);
  }
}
 
// This code is contributed by Shubham Singh


Python3
# Python program for the above approach
dp = [[0 for i in range(31)] for j in range(200005)]
 
# Function to build the dp array
# which stores the set bits for
# each bit position till 200005.
def count_set_bits():
    N = 200005
    for i in range(1, N):
        for j in range(31):
           
            # If j th bit is set assign
            # dp[i][j] =1 where dp[i][j] means
            # number of jth bits set till i
            if (i & (1 << j)):
                dp[i][j] = 1
                 
            # Calculate the prefix sum
            dp[i][j] += dp[i - 1][j]
 
# Function to solve the queries
def solve_queries(q):
     
    # Call the function to
    # precalculate the dp array
    count_set_bits()
    for i in range(len(q)):
        l = q[i][0]
        r = q[i][1]
         
        # Initialize the max_set = INT_MIN to
        # check what count of set bit
        # majority of numbers in the range was set
        max_set = -2**32
         
        # For each bit check the
        # maximum numbers in the range
        # having the j th bit set
        for j in range(31):
            total_set = (dp[r][j] - dp[l - 1][j])
            max_set = max(max_set, total_set)
             
        # Total length of range - count of max
        # numbers having 1 bit set in the range
        print((r - l + 1) - max_set, end=" ")
 
# Driver Code
# Initialize the queries
queries =  [[1, 5],  [3, 4],  [5, 10],  [10, 15]]
 
solve_queries(queries)
 
# This code is contributed by Shubham Singh


C#
// C# code to implement the above approach
using System;
 
public class GFG{
 
  public static int[,] dp = new int[200005,31];
 
  // Function to build the dp array
  // which stores the set bits for
  // each bit position till 200005.
  public static void count_set_bits()
  {
    int N = 200005;
    for (int i = 1; i < N; i++)
    {
      for (int j = 0; j <= 30; j++)
      {
 
        // If j th bit is set assign
        // dp[i,j] =1 where dp[i,j] means
        // number of jth bits set till i
        if ((i & (1 << j))!=0)
          dp[i,j] = 1;
 
        // Calculate the prefix sum
        dp[i,j] += dp[i - 1,j];
      }
    }
  }
 
  // Function to solv e the queries
  public static void solve_queries(int[][] q)
  {
 
    // Call the function to
    // precalculate the dp array
    count_set_bits();
    for (int i = 0; i < q.Length; i++) {
 
      int l = q[i][0];
      int r = q[i][1];
 
      // Initialize the max_set = INT_MIN to
      // check what count of set bit
      // majority of numbers in the range was set
      int max_set = Int32.MinValue;
 
      // For each bit check the
      // maximum numbers in the range
      // having the j th bit set
      for (int j = 0; j <= 30; j++) {
        int total_set = (dp[r,j] - dp[l - 1,j]);
 
        max_set = Math.Max(max_set, total_set);
      }
 
      // Total length of range - count of max
      // numbers having 1 bit set in the range
      Console.Write((r - l + 1) - max_set + " ");
    }
  }
 
  // Driver Code
  static public void Main ()
  {
 
    // Initialize the queries
    int[][] queries = new int[][]
    {
      new int[] { 1, 5 },
      new int[] { 3, 4 },
      new int[] { 5, 10 },
      new int[] { 10, 15 }
    };
 
    solve_queries(queries);
  }
}
 
// This code is contributed by Shubham Singh


输出
2 1 3 0 

时间复杂度: O (31 * Q * n ) 其中 n 是最大范围的长度。
辅助空间: O(1)

高效方法:这种方法基于动态编程和前缀和技术。这可以通过在 31 位的每个位置使用dp[]数组存储到该范围的总设置位的计数来完成。这里dp[i][j]的状态表示从[1, i]i的第 j 位位置的总设置位。按照以下步骤解决上述问题:

  • count_set_bits()进行函数调用以使用前缀 sum预先计算dp[][]数组。
  • 现在遍历查询并分配l = q[i][0], r = q[i][1]
    • 初始化max_set = INT_MIN以存储设置了第j位的范围内元素的最大计数的计数。
    • 遍历[0, 30]中的位。
    • 计算由total_set = (dp[r][j] – dp[l – 1][j])设置的第 j位元素的数量。
    • 通过采用max(max_set, total_set)存储具有第 j位设置的元素的最大计数。
  • 通过从总长度(r-l+1)中减去max_set打印所需的最小移除量。

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
using namespace std;
 
int dp[200005][31];
 
// Function to build the dp array
// which stores the set bits for
// each bit position till 200005.
void count_set_bits()
{
    int N = 2e5 + 5;
    for (int i = 1; i < N; i++) {
        for (int j = 0; j <= 30; j++) {
            // If j th bit is set assign
            // dp[i][j] =1 where dp[i][j] means
            // number of jth bits set till i
            if (i & (1 << j))
                dp[i][j] = 1;
 
            // Calculate the prefix sum
            dp[i][j] += dp[i - 1][j];
        }
    }
}
 
// Function to solve the queries
void solve_queries(vector > q)
{
    // Call the function to
    // precalculate the dp array
    count_set_bits();
    for (int i = 0; i < q.size(); i++) {
 
        int l = q[i][0];
        int r = q[i][1];
 
        // Initialize the max_set = INT_MIN to
        // check what count of set bit
        // majority of numbers in the range was set
        int max_set = INT_MIN;
 
        // For each bit check the
        // maximum numbers in the range
        // having the j th bit set
        for (int j = 0; j <= 30; j++) {
            int total_set = (dp[r][j] - dp[l - 1][j]);
 
            max_set = max(max_set, total_set);
        }
 
        // Total length of range - count of max
        // numbers having 1 bit set in the range
        cout << (r - l + 1) - max_set << " ";
    }
}
 
// Driver Code
int main()
{
 
    // Initialize the queries
    vector > queries
        = { { 1, 5 }, { 3, 4 }, { 5, 10 }, { 10, 15 } };
 
    solve_queries(queries);
    return 0;
}

Java

// Java code to implement the above approach
import java.io.*;
 
class GFG
{
 
  public static int dp[][] = new int[200005][31];
 
  // Function to build the dp array
  // which stores the set bits for
  // each bit position till 200005.
  public static void count_set_bits()
  {
    int N = 200005;
    for (int i = 1; i < N; i++)
    {
      for (int j = 0; j <= 30; j++)
      {
 
        // If j th bit is set assign
        // dp[i][j] =1 where dp[i][j] means
        // number of jth bits set till i
        if ((i & (1 << j))!=0)
          dp[i][j] = 1;
 
        // Calculate the prefix sum
        dp[i][j] += dp[i - 1][j];
      }
    }
  }
 
  // Function to solv e the queries
  public static void solve_queries(int[][] q)
  {
 
    // Call the function to
    // precalculate the dp array
    count_set_bits();
    for (int i = 0; i < q.length; i++) {
 
      int l = q[i][0];
      int r = q[i][1];
 
      // Initialize the max_set = INT_MIN to
      // check what count of set bit
      // majority of numbers in the range was set
      int max_set = Integer.MIN_VALUE;
 
      // For each bit check the
      // maximum numbers in the range
      // having the j th bit set
      for (int j = 0; j <= 30; j++) {
        int total_set = (dp[r][j] - dp[l - 1][j]);
 
        max_set = Math.max(max_set, total_set);
      }
 
      // Total length of range - count of max
      // numbers having 1 bit set in the range
      System.out.print((r - l + 1) - max_set + " ");
    }
  }
 
  // Driver Code
  public static void main (String[] args)
  {
 
    // Initialize the queries
    int[][] queries = new int[][]
    {
      new int[] { 1, 5 },
      new int[] { 3, 4 },
      new int[] { 5, 10 },
      new int[] { 10, 15 }
    };
 
    solve_queries(queries);
  }
}
 
// This code is contributed by Shubham Singh

Python3

# Python program for the above approach
dp = [[0 for i in range(31)] for j in range(200005)]
 
# Function to build the dp array
# which stores the set bits for
# each bit position till 200005.
def count_set_bits():
    N = 200005
    for i in range(1, N):
        for j in range(31):
           
            # If j th bit is set assign
            # dp[i][j] =1 where dp[i][j] means
            # number of jth bits set till i
            if (i & (1 << j)):
                dp[i][j] = 1
                 
            # Calculate the prefix sum
            dp[i][j] += dp[i - 1][j]
 
# Function to solve the queries
def solve_queries(q):
     
    # Call the function to
    # precalculate the dp array
    count_set_bits()
    for i in range(len(q)):
        l = q[i][0]
        r = q[i][1]
         
        # Initialize the max_set = INT_MIN to
        # check what count of set bit
        # majority of numbers in the range was set
        max_set = -2**32
         
        # For each bit check the
        # maximum numbers in the range
        # having the j th bit set
        for j in range(31):
            total_set = (dp[r][j] - dp[l - 1][j])
            max_set = max(max_set, total_set)
             
        # Total length of range - count of max
        # numbers having 1 bit set in the range
        print((r - l + 1) - max_set, end=" ")
 
# Driver Code
# Initialize the queries
queries =  [[1, 5],  [3, 4],  [5, 10],  [10, 15]]
 
solve_queries(queries)
 
# This code is contributed by Shubham Singh

C#

// C# code to implement the above approach
using System;
 
public class GFG{
 
  public static int[,] dp = new int[200005,31];
 
  // Function to build the dp array
  // which stores the set bits for
  // each bit position till 200005.
  public static void count_set_bits()
  {
    int N = 200005;
    for (int i = 1; i < N; i++)
    {
      for (int j = 0; j <= 30; j++)
      {
 
        // If j th bit is set assign
        // dp[i,j] =1 where dp[i,j] means
        // number of jth bits set till i
        if ((i & (1 << j))!=0)
          dp[i,j] = 1;
 
        // Calculate the prefix sum
        dp[i,j] += dp[i - 1,j];
      }
    }
  }
 
  // Function to solv e the queries
  public static void solve_queries(int[][] q)
  {
 
    // Call the function to
    // precalculate the dp array
    count_set_bits();
    for (int i = 0; i < q.Length; i++) {
 
      int l = q[i][0];
      int r = q[i][1];
 
      // Initialize the max_set = INT_MIN to
      // check what count of set bit
      // majority of numbers in the range was set
      int max_set = Int32.MinValue;
 
      // For each bit check the
      // maximum numbers in the range
      // having the j th bit set
      for (int j = 0; j <= 30; j++) {
        int total_set = (dp[r,j] - dp[l - 1,j]);
 
        max_set = Math.Max(max_set, total_set);
      }
 
      // Total length of range - count of max
      // numbers having 1 bit set in the range
      Console.Write((r - l + 1) - max_set + " ");
    }
  }
 
  // Driver Code
  static public void Main ()
  {
 
    // Initialize the queries
    int[][] queries = new int[][]
    {
      new int[] { 1, 5 },
      new int[] { 3, 4 },
      new int[] { 5, 10 },
      new int[] { 10, 15 }
    };
 
    solve_queries(queries);
  }
}
 
// This code is contributed by Shubham Singh
输出
2 1 3 0 

时间复杂度: O(31 * Q)
辅助空间: O(n)