Given array A[] of size N with all elements zero, along with given M segments in the form of array B[][2]. You have q queries in array Q[] in ith query you have to turn Q[i]th element of A[] into 1, the task for this problem is to find the minimum number of queries to have at least one segment from M segments in which the number of 1’s in the segment strictly greater than the number of zeros.
Examples:
Input: N = 5, B[][2] = {{1, 2}, {4, 5}, {1, 5}, {1, 3}, {2, 4}}, Q[] = {5, 3, 1, 2, 4}
Output: 3
Explanation: Initially A[] = {0, 0, 0, 0, 0}
- For the first query, Q[1] = 5 so turn Q[1]’th index of array A[] one. A[] becomes {0, 0, 0, 0, 1}. After performing this query still, there is no segment from M segments that has more 1’s than 0’s.
- For the second query, Q[2] = 3 so turn Q[2]’th index of array A[] one. A[] becomes {0, 0, 1, 0, 1}. After performing this query still, there is no segment from M segments that has more 1’s than 0’s.
- For the third query, Q[3] = 1 so turn Q[3]’th index of array A[] one. A[] becomes {1, 0, 1, 0, 1}. After performing this query segments B[3] = {1, 5} and B[4] = {1, 3} has more 1’s than 0’s.
So the minimum number of queries to have at least one segment with more 1’s than 0’s is 3.
Input: N = 5, B[][2] = {{1, 5}, {1, 3}}, Q[] = {4, 1, 2, 3, 5}
Output: 3
Naïve Approach: The basic way to solve the problem is as follows:
This can be done in each query checking for all segments whether it has more 1’s than 0’s.
Time Complexity: O(N * M * Q)
Auxiliary Space: O(1)
Efficient Approach: To solve the problem follow the below idea:
- Binary Search can be used to solve this problem. function f(n) is true if after n’th query at least one segment from M segments has more 1’s than 0’s else f(n) will be false. This is monotonic function of type “FFFTTTT”. Using binary search lets find first time when this function will become true that will be answer of this problem.
- To check if given segment has more 1’s than 0’s prefix sum array can be used to check for each M segment in O(1) time complexity.
Below are the steps for the above approach:
- check() function checks if there is at least one segment with more 1’s than 0’s within the first mid queries.
- It initializes an array pre of size N+1 to store the prefix sum of 1’s from the queries.
- It sets the first mid elements of pre to 1, indicating the 1’s from the first mid queries.
- It then computes the prefix sum of the pre array.
-
For each segment in B, it calculates the number of 1’s and 0’s within that segment.
- If there is at least one segment with more 1’s than 0’s, it returns true.
- Otherwise, it returns false.
- findMinimumQueries function finds the minimum number of queries required to have at least one segment with more 1’s than 0’s within the given M segments.
- It initializes low to 1 and high to q for binary search.
- Inside the loop, it calculates the middle value mid as the average of low and high.
-
It then calls the check() function with mid as an argument to check if there’s at least one segment with more 1’s than 0’s within the first mid queries.
- If such a segment exists, it updates high to mid.
- If not, it updates low to mid + 1.
- Return the stored minimum queries in the end.
Below is the implementation of the above approach:
#include <bits/stdc++.h> using namespace std;
// Function to check if queries are performed // till mid will there be at least one segment // with more 1's than 0's bool check( int mid, int N, int B[][2], int M, int Q[])
{ // Creating array pre[] of size N
vector< int > pre(N + 1, 0);
// Performing first mid queries
for ( int i = 0; i < mid; i++)
pre[Q[i]] = 1;
// Forming prefix sum of this array
for ( int i = 1; i <= N; i++)
pre[i] = pre[i] + pre[i - 1];
// Checking if given M segments
for ( int i = 0; i < M; i++) {
// Size of the given segment
int sizeOfSegment = B[i][1] - B[i][0] + 1;
// Number of one's it has
int numberOfOnes = pre[B[i][1]] - pre[B[i][0] - 1];
// Number of zeros it has
int numberOfZeros = sizeOfSegment - numberOfOnes;
// If the number of one's is greater than
// zero's then return true
if (numberOfOnes > numberOfZeros)
return true ;
}
// If the number of one's is not greater than
// zero's then return false
return false ;
} // Function to find Minimum number of queries // to have at least one segment with more 1's // than 0's from given M segments int findMinimumQueries( int N, int B[][2], int M, int Q[],
int q)
{ // Range of binary search
int low = 1, high = q;
int min_query = 0;
// Running a loop until high
// is not equal to low
while (high - low > 1) {
// mid is the average of low and high
int mid = (low + high) / 2;
// Checking the test function
if (check(mid, N, B, M, Q)) {
min_query = mid;
high = mid - 1;
}
else {
low = mid + 1;
}
}
return min_query;
} // Driver Code int main()
{ // Input 1
int N = 5;
int B[][2] = { { 1, 2 },
{ 4, 5 },
{ 1, 5 },
{ 1, 3 },
{ 2, 4 } };
int M = 5;
int Q[] = { 5, 3, 1, 2, 4 };
int q = 5;
// Function Call
cout << findMinimumQueries(N, B, M, Q, q) << endl;
// Input 2
int N1 = 5;
int B1[][2] = { { 1, 5 }, { 1, 3 } };
int M1 = 2;
int Q1[] = { 4, 1, 2, 3, 5 };
int q1 = 5;
// Function Call
cout << findMinimumQueries(N1, B1, M1, Q1, q1) << endl;
return 0;
} |
import java.util.*;
class Main {
// Function to check if queries are performed
// till mid will there be at least one segment
// with more 1's than 0's
static boolean check( int mid, int N, int [][] B, int M, int [] Q) {
// Creating array pre[] of size N
int [] pre = new int [N + 1 ];
// Performing first mid queries
for ( int i = 0 ; i < mid; i++)
pre[Q[i]] = 1 ;
// Forming prefix sum of this array
for ( int i = 1 ; i <= N; i++)
pre[i] = pre[i] + pre[i - 1 ];
// Checking if given M segments
for ( int i = 0 ; i < M; i++) {
// Size of given segment
int sizeOfSegment = B[i][ 1 ] - B[i][ 0 ] + 1 ;
// Number of one's it has
int numberOfOnes = pre[B[i][ 1 ]] - pre[B[i][ 0 ] - 1 ];
// Number of zeros it has
int numberOfZeros = sizeOfSegment - numberOfOnes;
// If number of one's is greater than
// zero's than return true
if (numberOfOnes > numberOfZeros)
return true ;
}
// If number of one's is not greater than
// zero's than return false
return false ;
}
// Function to find Minimum number of queries
// to have at least one segment with more 1's
// than 0's from given M segments
static int findMinimumQueries( int N, int [][] B, int M, int [] Q, int q) {
// Range of binary search
int low = 1 , high = q;
int min_query = 0 ;
// Running loop till high
// is not equal to low
while (high - low > 1 ) {
// mid is average of low and high
int mid = (low + high) / 2 ;
// Checking test function
if (check(mid, N, B, M, Q)) {
min_query = mid;
high = mid - 1 ;
} else {
low = mid + 1 ;
}
}
return min_query;
}
// Driver Code
public static void main(String[] args) {
// Input 1
int N = 5 ;
int [][] B = { { 1 , 2 }, { 4 , 5 }, { 1 , 5 }, { 1 , 3 }, { 2 , 4 } };
int M = 5 ;
int [] Q = { 5 , 3 , 1 , 2 , 4 };
int q = 5 ;
// Function Call
System.out.println(findMinimumQueries(N, B, M, Q, q));
// Input 2
int N1 = 5 ;
int [][] B1 = { { 1 , 5 }, { 1 , 3 } };
int M1 = 2 ;
int [] Q1 = { 4 , 1 , 2 , 3 , 5 };
int q1 = 5 ;
// Function Call
System.out.println(findMinimumQueries(N1, B1, M1, Q1, q1));
}
} //This code is Contributed by chinmaya121221 |
def check(mid, N, B, M, Q):
# Creating a list pre[] of size N
pre = [ 0 ] * (N + 1 )
# Performing first mid queries
for i in range (mid):
pre[Q[i]] = 1
# Forming the prefix sum of this list
for i in range ( 1 , N + 1 ):
pre[i] = pre[i] + pre[i - 1 ]
# Checking if given M segments
for i in range (M):
# Size of the given segment
size_of_segment = B[i][ 1 ] - B[i][ 0 ] + 1
# Number of ones it has
number_of_ones = pre[B[i][ 1 ]] - pre[B[i][ 0 ] - 1 ]
# Number of zeros it has
number_of_zeros = size_of_segment - number_of_ones
# If the number of ones is greater than
# the number of zeros, then return True
if number_of_ones > number_of_zeros:
return True
# If the number of ones is not greater than
# the number of zeros, then return False
return False
def find_minimum_queries(N, B, M, Q, q):
# Range of binary search
low = 1
high = q
min_query = 0
# Running a loop until high
# is not equal to low
while high - low > 1 :
# mid is the average of low and high
mid = (low + high) / / 2
# Checking the test function
if check(mid, N, B, M, Q):
min_query = mid
high = mid - 1
else :
low = mid + 1
return min_query
# Driver Code if __name__ = = "__main__" :
# Input 1
N = 5
B = [[ 1 , 2 ], [ 4 , 5 ], [ 1 , 5 ], [ 1 , 3 ], [ 2 , 4 ]]
M = 5
Q = [ 5 , 3 , 1 , 2 , 4 ]
q = 5
# Function Call
print (find_minimum_queries(N, B, M, Q, q))
# Input 2
N1 = 5
B1 = [[ 1 , 5 ], [ 1 , 3 ]]
M1 = 2
Q1 = [ 4 , 1 , 2 , 3 , 5 ]
q1 = 5
# Function Call
print (find_minimum_queries(N1, B1, M1, Q1, q1))
|
using System;
using System.Collections.Generic;
class Program
{ // Function to check if queries are performed
// till mid will there be at least one segment
// with more 1's than 0's
static bool Check( int mid, int N, int [][] B, int M, int [] Q)
{
// Creating array pre[] of size N
List< int > pre = new List< int >( new int [N + 1]);
// Performing first mid queries
for ( int i = 0; i < mid; i++)
pre[Q[i]] = 1;
// Forming prefix sum of this array
for ( int i = 1; i <= N; i++)
pre[i] = pre[i] + pre[i - 1];
// Checking if given M segments
for ( int i = 0; i < M; i++)
{
// Size of the given segment
int sizeOfSegment = B[i][1] - B[i][0] + 1;
// Number of one's it has
int numberOfOnes = pre[B[i][1]] - pre[B[i][0] - 1];
// Number of zeros it has
int numberOfZeros = sizeOfSegment - numberOfOnes;
// If the number of one's is greater than
// zero's then return true
if (numberOfOnes > numberOfZeros)
return true ;
}
// If the number of one's is not greater than
// zero's then return false
return false ;
}
// Function to find Minimum number of queries
// to have at least one segment with more 1's
// than 0's from given M segments
static int FindMinimumQueries( int N, int [][] B, int M, int [] Q, int q)
{
// Range of binary search
int low = 1;
int high = q;
int min_query = 0;
// Running a loop until high
// is not equal to low
while (high - low > 1)
{
// mid is the average of low and high
int mid = (low + high) / 2;
// Checking the test function
if (Check(mid, N, B, M, Q))
{
min_query = mid;
high = mid - 1;
}
else
{
low = mid + 1;
}
}
return min_query;
}
// Driver Code
static void Main()
{
// Input 1
int N = 5;
int [][] B = {
new int [] {1, 2},
new int [] {4, 5},
new int [] {1, 5},
new int [] {1, 3},
new int [] {2, 4}
};
int M = 5;
int [] Q = {5, 3, 1, 2, 4};
int q = 5;
// Function Call
Console.WriteLine(FindMinimumQueries(N, B, M, Q, q));
// Input 2
int N1 = 5;
int [][] B1 = {
new int [] {1, 5},
new int [] {1, 3}
};
int M1 = 2;
int [] Q1 = {4, 1, 2, 3, 5};
int q1 = 5;
// Function Call
Console.WriteLine(FindMinimumQueries(N1, B1, M1, Q1, q1));
}
} //Contributed by tyagdh0xk |
// JavaScript code to implement the approach // Function to check if queries are performed // till mid will there be at least one segment // with more 1's than 0's function check(mid, N, B, M, Q) {
// Creating an array pre of size N
const pre = new Array(N + 1).fill(0);
// Performing the first mid queries
for (let i = 0; i < mid; i++) {
pre[Q[i]] = 1;
}
// Forming a prefix sum of this array
for (let i = 1; i <= N; i++) {
pre[i] = pre[i] + pre[i - 1];
}
// Checking if given M segments
for (let i = 0; i < M; i++) {
// Size of the given segment
const sizeOfSegment = B[i][1] - B[i][0] + 1;
// Number of ones it has
const numberOfOnes = pre[B[i][1]] - pre[B[i][0] - 1];
// Number of zeros it has
const numberOfZeros = sizeOfSegment - numberOfOnes;
// If the number of ones is greater than
// the number of zeros, return true
if (numberOfOnes > numberOfZeros) {
return true ;
}
}
// If the number of ones is not greater than
// the number of zeros, return false
return false ;
} // Function to find Minimum number of queries // to have at least one segment with more 1's // than 0's from given M segments function findMinimumQueries(N, B, M, Q, q) {
// Range of binary search
let low = 1;
let high = q;
let min_query = 0;
// Running a loop until high
// is not equal to low
while (high - low > 1) {
// mid is the average of low and high
const mid = Math.floor((low + high) / 2);
// Checking the test function
if (check(mid, N, B, M, Q)) {
min_query = mid;
high = mid - 1;
} else {
low = mid + 1;
}
}
return min_query;
} // Driver Code // Input 1 const N = 5; const B = [[1, 2], [4, 5], [1, 5], [1, 3], [2, 4]]; const M = 5; const Q = [5, 3, 1, 2, 4]; const q = 5; // Function Call console.log(findMinimumQueries(N, B, M, Q, q)); // Input 2 const N1 = 5; const B1 = [[1, 5], [1, 3]]; const M1 = 2; const Q1 = [4, 1, 2, 3, 5]; const q1 = 5; // Function Call console.log(findMinimumQueries(N1, B1, M1, Q1, q1)); |
3 3
Time Complexity: O((N + M)*logQ)
Auxiliary Space: O(N)