import math
class GFG:
# Function to return the minimum removals
# required so that the array satisfies
# the given condition
def removeMinElements(self, a):
n = len(a)
rMimQ = self.RangeMinimumQuery()
minTree = rMimQ.createSegmentTree(a)
rMaxQ = self.RangeMaximumQuery()
maxTree = rMaxQ.createSegmentTree(a)
start = 0
end = 0
# To store min and max in the current window
min_val = 0
max_val = 0
maxValidLen = 0
while end < n:
min_val = rMimQ.rangeMinimumQuery(minTree, start, end, n)
max_val = rMaxQ.rangeMaximumQuery(maxTree, start, end, n)
if 2 * min_val <= max_val:
start += 1
else:
maxValidLen = max(maxValidLen, end - start + 1)
end += 1
return n - maxValidLen
class RangeMinimumQuery:
def createSegmentTree(self, input):
n = len(input)
segTreeSize = 2 * self.get_next_power_of_two(n) - 1
segmentTree = [0] * segTreeSize
self.createSegmentTreeUtil(segmentTree, input, 0, n - 1, 0)
return segmentTree
def createSegmentTreeUtil(self, segmentTree, input, low, high, pos):
if low == high:
# It's a leaf node
segmentTree[pos] = input[low]
return
# Construct left and right subtrees and then
# update value for the current node
mid = (low + high) // 2
self.createSegmentTreeUtil(segmentTree, input, low, mid, (2 * pos + 1))
self.createSegmentTreeUtil(segmentTree, input, mid + 1, high, (2 * pos + 2))
segmentTree[pos] = min(segmentTree[2 * pos + 1], segmentTree[2 * pos + 2])
def rangeMinimumQuery(self, segmentTree, from_, to, inputSize):
return self.rangeMinimumQueryUtil(segmentTree, 0, inputSize - 1, from_, to, 0)
def rangeMinimumQueryUtil(self, segmentTree, low, high, from_, to, pos):
# Total overlap
if from_ <= low and to >= high:
return segmentTree[pos]
# No overlap
if from_ > high or to < low:
return float('inf')
# Partial overlap
mid = (low + high) // 2
left = self.rangeMinimumQueryUtil(segmentTree, low, mid, from_, to, (2 * pos + 1))
right = self.rangeMinimumQueryUtil(segmentTree, mid + 1, high, from_, to, (2 * pos + 2))
return min(left, right)
# Move the get_next_power_of_two method here
def get_next_power_of_two(self, n):
log_part = math.ceil(math.log(n) / math.log(2))
return 2 ** log_part
class RangeMaximumQuery:
# Move the get_next_power_of_two method here
def get_next_power_of_two(self, n):
log_part = math.ceil(math.log(n) / math.log(2))
return 2 ** log_part
def createSegmentTree(self, input):
n = len(input)
segTreeSize = 2 * self.get_next_power_of_two(n) - 1
segmentTree = [0] * segTreeSize
self.createSegmentTreeUtil(segmentTree, input, 0, n - 1, 0)
return segmentTree
def createSegmentTreeUtil(self, segmentTree, input, low, high, pos):
if low == high:
# It's a leaf node
segmentTree[pos] = input[low]
return
# Construct left and right subtrees and then
# update value for the current node
mid = (low + high) // 2
self.createSegmentTreeUtil(segmentTree, input, low, mid, (2 * pos + 1))
self.createSegmentTreeUtil(segmentTree, input, mid + 1, high, (2 * pos + 2))
segmentTree[pos] = max(segmentTree[2 * pos + 1], segmentTree[2 * pos + 2])
def rangeMaximumQuery(self, segmentTree, from_, to, inputSize):
return self.rangeMaximumQueryUtil(segmentTree, 0, inputSize - 1, from_, to, 0)
def rangeMaximumQueryUtil(self, segmentTree, low, high, from_, to, pos):
# Total overlap
if from_ <= low and to >= high:
return segmentTree[pos]
# No overlap
if from_ > high or to < low:
return float('-inf')
# Partial overlap
mid = (low + high) // 2
left = self.rangeMaximumQueryUtil(segmentTree, low, mid, from_, to, (2 * pos + 1))
right = self.rangeMaximumQueryUtil(segmentTree, mid + 1, high, from_, to, (2 * pos + 2))
return max(left, right)
# Driver code
if __name__ == "__main__":
a = [4, 5, 100, 9, 10, 11, 12, 15, 200]
gfg = GFG()
print(gfg.removeMinElements(a))