import math
# Structure to represent a query range
class Query:
def __init__(self, L, R, index, odd, even):
self.L = L
self.R = R
self.index = index
self.odd = odd
self.even = even
# Function used to sort all queries so that
# all queries of the same block are arranged
# together and within a block, queries are
# sorted in increasing order of R values.
def compare(x, y):
# Different blocks, sort by block.
if x.L // block != y.L // block:
return x.L // block < y.L // block
# Same block, sort by R value
return x.R < y.R
# Function used to sort all queries in order of their
# index value so that results of queries can be printed
# in the same order as input
def compare1(x, y):
return x.index < y.index
# Function to Add elements
# of the current range
def add(currL, a):
global count_oddP
# __builtin_parity(x) returns True (1)
# if the number has odd parity else
# it returns False (0) for even parity.
if bin(a[currL]).count('1') % 2 == 1:
count_oddP += 1
# Function to remove elements
# of the previous range
def remove(currR, a):
global count_oddP
# __builtin_parity(x) returns True (1)
# if the number has odd parity else
# it returns False (0) for even parity.
if bin(a[currR]).count('1') % 2 == 1:
count_oddP -= 1
# Function to generate the result of queries
def queryResults(a, n, q, m):
global block, count_oddP
# Initialize number of odd parity
# elements to 0
count_oddP = 0
# Find block size
block = int(math.sqrt(n))
# Sort all queries so that queries of
# the same blocks are arranged together.
q.sort(key=lambda x: (x.L // block, x.R))
# Initialize current L, current R, and
# current result
currL, currR = 0, 0
for i in range(m):
# L and R values of the current range
L, R = q[i].L, q[i].R
# Add Elements of the current range
while currR <= R:
add(currR, a)
currR += 1
while currL > L:
add(currL - 1, a)
currL -= 1
# Remove element of the previous range
while currR > R + 1:
remove(currR - 1, a)
currR -= 1
while currL < L:
remove(currL, a)
currL += 1
q[i].odd = count_oddP
q[i].even = R - L + 1 - count_oddP
# Function to display the results of
# queries in their initial order
def printResults(q, m):
q.sort(key=lambda x: x.index)
for i in range(m):
print(q[i].odd, q[i].even)
# Driver Code
if __name__ == "__main__":
arr = [5, 2, 3, 1, 4, 8, 10, 12]
n = len(arr)
q = [Query(1, 3, 0, 0, 0),
Query(0, 4, 1, 0, 0),
Query(4, 7, 2, 0, 0)]
m = len(q)
queryResults(arr, n, q, m)
printResults(q, m)