HackerEarth Practice Problem {Binary Queries}
By: Saptarshi Roy
Tags: Programming, Binary Operations, Computer Science, Arrays, Hackerearth

Hi readers, I just happen to practice a lot of competitive programming problems, and come across multiple scenarios, which enables me to learn and come up with proper algo, to provide solution in the best complexity possible. I came across, this recent rather easy problem on HackerEarth, and since this being my first post on Medium, thought about sharing my experience here. Without much ado, here goes the same:

Problem Statement:

Some problems appear hard though they are very easy. Today Aakash is stuck in a range query problem. He has been given an array with only numbers 0 and 1. There are two types of queries -

0 L R : Check whether the number formed from the array elements L to R is even or odd and print EVEN or ODD respectively. Number formation is the binary number from the bits status in the array L to R

1 X : Flip the Xth bit in the array

Indexing is 1 based

Input

First line contains a number N and Q as input. Next line contains N space separated 0 or 1. Next Q lines contain description of each query

Output

Output for only query type 0 L R whether the number in range L to R is “EVEN” or “ODD” (without quotes).

Constraints

1≤ N ≤ 10⁶

1≤ L ≤ R ≤ 10⁶

1≤ Q ≤ 10⁶

1≤ X ≤ N

SAMPLE INPUT

5 2

1 0 1 1 0

1 2

0 1 4

SAMPLE OUTPUT

ODD

Explanation

Our first query is 1 2 that means that we have to flip the 2nd bit in the given array so now our array becomes 1 1 1 1 0

2nd query is 0 1 4 which means that if i pick the subarray 1 to 4 i.e 1 1 1 1 then the number formed by decimal representation of this binary number is of what kind ?. Here the number formed is 15 so its odd and ODD is the output

Towards Solution

The problem asks for two things primarily, one related to just updation of a single cell in the array, and the other that of working with a sub-array.

Now, the first part appears to be quite easy (Query type: 1), which involves just accessing the array and updating the content of it. And since we are using our data structure as array, we know this operation will be done in O(1) time for any position { why? coz, arrays are stored as contiguous cells in memory, so trying to access a particular index means just adding the (size of array data type * index) to the base pointer location }.

The second part(Query Type:0), is a bit tricky here, as here we need to deal with the sub-array , convert that to decimal and check whether that is ODD or EVEN, A standard approach can be to read the sub-array from the rightmost location and multiply its value with (2 to power index val) and adding all of them up and coming to the decimal representation.

The 0(N) Approach:

Ex: 1101 in binary to decimal → (1 * 2 to pow (0)) + (0 * 2 to pow(1)) + (1 * 2 to pow (2)) + (1 * 2 to pow(3)) ===> 1+0+4+8 = 13.

So using the above logic we can easily write a loop and calculate the decimal val and find out whether that is even or odd by doing %2 after that. This approach has O(N) time , where N is the size of the sub array.

The O(1) Approach

Though the above approach looks fine, but there is a better way to solve that in just O(1) time. To understand this, we need to use our old school friend ( Number System). From that , we will use two points: EVEN + EVEN = EVEN & EVEN + ODD = ODD . Now coming to our binary to decimal representation , we see that for any such binary set of bits, it is the rightmost bit’s value that represents whether that no will be ODD or EVEN (why? coz, in our earlier calculation , we saw the binary gets converted to decimal using the exploded calculation based on indexing , so in that case for any values up the higher order, starting from 1 to up whether the bit is 0 or 1, will always result in an EVEN sum , and the only concern is the rightmost ( 0 th ) bit, if that is set as 1 then we add {1*2 to pow(0)} i.e is 1 (ODD)to it thereby making the sum as ODD, and if that bit is 0 then we add {0*2 to pow(0)} i.e 0 (EVEN) to it thereby making the sum as EVEN.

Thus our task at hand boils down to check whether the rightmost cell value in the selected subarray has a value of 0 or 1, which becomes an array access problem of complexity time O(1) again.

So here goes the entire solution snippet in JAVA:

import java.io.BufferedReader;

import java.io.InputStreamReader; class TestClass {

public static void main(String args[] ) throws Exception {



BufferedReader br = new BufferedReader(new InputStreamReader(System.in));



String line1 = br.readLine(); // Reading input from STDIN

String[] arr = line1.split(“ “);

int no_queries = Integer.parseInt(arr[1]);

String[] list = br.readLine().split(“ “);



for(int i =1; i<=no_queries; i++){

String[] query = br.readLine().split(“ “);



if(query[0].equals(“1”)){

// flip

int index = Integer.parseInt(query[1])-1;

if(list[index].equals(“1”)){

list[index] = “0”;

}else{

list[index] = “1”;

}

}else{

// ODD or EVEN

int r = Integer.parseInt(query[2]) — 1;

if(list[r].equals(“1”)){

System.out.println(“ODD”);

}else{

System.out.println(“EVEN”);

}



}

} }

}

Just a point to be added from my experience , i first tried solving the problem with Scanner Class to read the input , but that made me miss the time limit at HackerEarth, then switched over to BufferedReader & InputStreamReader. There is a subtle difference between the two, with Scanner taking more time to process, since it does parsing of input data, whereas its counterpart just reads in the character stream.

That’s all folks, hope it helps you in some way. Will keep on posting more future experiences.