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:
C++
#include <bits/stdc++.h>
using namespace std;
bool check( int mid, int N, int B[][2], int M, int Q[])
{
vector< int > pre(N + 1, 0);
for ( int i = 0; i < mid; i++)
pre[Q[i]] = 1;
for ( int i = 1; i <= N; i++)
pre[i] = pre[i] + pre[i - 1];
for ( int i = 0; i < M; i++) {
int sizeOfSegment = B[i][1] - B[i][0] + 1;
int numberOfOnes = pre[B[i][1]] - pre[B[i][0] - 1];
int numberOfZeros = sizeOfSegment - numberOfOnes;
if (numberOfOnes > numberOfZeros)
return true ;
}
return false ;
}
int findMinimumQueries( int N, int B[][2], int M, int Q[],
int q)
{
int low = 1, high = q;
int min_query = 0;
while (high - low > 1) {
int mid = (low + high) / 2;
if (check(mid, N, B, M, Q)) {
min_query = mid;
high = mid - 1;
}
else {
low = mid + 1;
}
}
return min_query;
}
int main()
{
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;
cout << findMinimumQueries(N, B, M, Q, q) << endl;
int N1 = 5;
int B1[][2] = { { 1, 5 }, { 1, 3 } };
int M1 = 2;
int Q1[] = { 4, 1, 2, 3, 5 };
int q1 = 5;
cout << findMinimumQueries(N1, B1, M1, Q1, q1) << endl;
return 0;
}
|
Java
import java.util.*;
class Main {
static boolean check( int mid, int N, int [][] B, int M, int [] Q) {
int [] pre = new int [N + 1 ];
for ( int i = 0 ; i < mid; i++)
pre[Q[i]] = 1 ;
for ( int i = 1 ; i <= N; i++)
pre[i] = pre[i] + pre[i - 1 ];
for ( int i = 0 ; i < M; i++) {
int sizeOfSegment = B[i][ 1 ] - B[i][ 0 ] + 1 ;
int numberOfOnes = pre[B[i][ 1 ]] - pre[B[i][ 0 ] - 1 ];
int numberOfZeros = sizeOfSegment - numberOfOnes;
if (numberOfOnes > numberOfZeros)
return true ;
}
return false ;
}
static int findMinimumQueries( int N, int [][] B, int M, int [] Q, int q) {
int low = 1 , high = q;
int min_query = 0 ;
while (high - low > 1 ) {
int mid = (low + high) / 2 ;
if (check(mid, N, B, M, Q)) {
min_query = mid;
high = mid - 1 ;
} else {
low = mid + 1 ;
}
}
return min_query;
}
public static void main(String[] args) {
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 ;
System.out.println(findMinimumQueries(N, B, M, Q, q));
int N1 = 5 ;
int [][] B1 = { { 1 , 5 }, { 1 , 3 } };
int M1 = 2 ;
int [] Q1 = { 4 , 1 , 2 , 3 , 5 };
int q1 = 5 ;
System.out.println(findMinimumQueries(N1, B1, M1, Q1, q1));
}
}
|
Python
def check(mid, N, B, M, Q):
pre = [ 0 ] * (N + 1 )
for i in range (mid):
pre[Q[i]] = 1
for i in range ( 1 , N + 1 ):
pre[i] = pre[i] + pre[i - 1 ]
for i in range (M):
size_of_segment = B[i][ 1 ] - B[i][ 0 ] + 1
number_of_ones = pre[B[i][ 1 ]] - pre[B[i][ 0 ] - 1 ]
number_of_zeros = size_of_segment - number_of_ones
if number_of_ones > number_of_zeros:
return True
return False
def find_minimum_queries(N, B, M, Q, q):
low = 1
high = q
min_query = 0
while high - low > 1 :
mid = (low + high) / / 2
if check(mid, N, B, M, Q):
min_query = mid
high = mid - 1
else :
low = mid + 1
return min_query
if __name__ = = "__main__" :
N = 5
B = [[ 1 , 2 ], [ 4 , 5 ], [ 1 , 5 ], [ 1 , 3 ], [ 2 , 4 ]]
M = 5
Q = [ 5 , 3 , 1 , 2 , 4 ]
q = 5
print (find_minimum_queries(N, B, M, Q, q))
N1 = 5
B1 = [[ 1 , 5 ], [ 1 , 3 ]]
M1 = 2
Q1 = [ 4 , 1 , 2 , 3 , 5 ]
q1 = 5
print (find_minimum_queries(N1, B1, M1, Q1, q1))
|
C#
using System;
using System.Collections.Generic;
class Program
{
static bool Check( int mid, int N, int [][] B, int M, int [] Q)
{
List< int > pre = new List< int >( new int [N + 1]);
for ( int i = 0; i < mid; i++)
pre[Q[i]] = 1;
for ( int i = 1; i <= N; i++)
pre[i] = pre[i] + pre[i - 1];
for ( int i = 0; i < M; i++)
{
int sizeOfSegment = B[i][1] - B[i][0] + 1;
int numberOfOnes = pre[B[i][1]] - pre[B[i][0] - 1];
int numberOfZeros = sizeOfSegment - numberOfOnes;
if (numberOfOnes > numberOfZeros)
return true ;
}
return false ;
}
static int FindMinimumQueries( int N, int [][] B, int M, int [] Q, int q)
{
int low = 1;
int high = q;
int min_query = 0;
while (high - low > 1)
{
int mid = (low + high) / 2;
if (Check(mid, N, B, M, Q))
{
min_query = mid;
high = mid - 1;
}
else
{
low = mid + 1;
}
}
return min_query;
}
static void Main()
{
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;
Console.WriteLine(FindMinimumQueries(N, B, M, Q, q));
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;
Console.WriteLine(FindMinimumQueries(N1, B1, M1, Q1, q1));
}
}
|
Javascript
function check(mid, N, B, M, Q) {
const pre = new Array(N + 1).fill(0);
for (let i = 0; i < mid; i++) {
pre[Q[i]] = 1;
}
for (let i = 1; i <= N; i++) {
pre[i] = pre[i] + pre[i - 1];
}
for (let i = 0; i < M; i++) {
const sizeOfSegment = B[i][1] - B[i][0] + 1;
const numberOfOnes = pre[B[i][1]] - pre[B[i][0] - 1];
const numberOfZeros = sizeOfSegment - numberOfOnes;
if (numberOfOnes > numberOfZeros) {
return true ;
}
}
return false ;
}
function findMinimumQueries(N, B, M, Q, q) {
let low = 1;
let high = q;
let min_query = 0;
while (high - low > 1) {
const mid = Math.floor((low + high) / 2);
if (check(mid, N, B, M, Q)) {
min_query = mid;
high = mid - 1;
} else {
low = mid + 1;
}
}
return min_query;
}
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;
console.log(findMinimumQueries(N, B, M, Q, q));
const N1 = 5;
const B1 = [[1, 5], [1, 3]];
const M1 = 2;
const Q1 = [4, 1, 2, 3, 5];
const q1 = 5;
console.log(findMinimumQueries(N1, B1, M1, Q1, q1));
|
Time Complexity: O((N + M)*logQ) Auxiliary Space: O(N)
|