# Python3 program to find the number
# of Powerful numbers in subarray
# using segment tree
import math
MAX = 100000
# Size of segment tree = 2^{log(MAX)+1}
tree = [0]*(3 * MAX)
arr = [0]*(MAX)
powerful = [False]*(MAX + 1)
# Function to check if the
# number is powerful
def isPowerful(n):
# First divide the number
# repeatedly by 2
while (n % 2 == 0):
power = 0
while (n % 2 == 0):
n = int(n / 2)
power += 1
# If only 2^1 divides
# n (not higher powers),
# then return false
if (power == 1):
return False
# If n is not a power of 2 then
# this loop will execute
# repeat above process
for factor in range(3, int(math.sqrt(n)) + 1, 2):
# Find highest power of
# "factor" that divides n
power = 0
while (n % factor == 0):
n = int(n / factor)
power += 1
# If only factor^1 divides n
# (not higher powers),
# then return false
if (power == 1):
return False
# n must be 1 now if it is not
# a prime number. Since prime
# numbers are not powerful,
# we return false if n is not 1.
return (n == 1)
# Function to build the array
def BuildArray(Input, n):
for i in range(n):
# Check if input[i] is
# a Powerful number or not
if (powerful[Input[i]]):
arr[i] = 1
else:
arr[i] = 0
return
# A utility function to get the middle
# index from corner indexes.
def getMid(s, e):
return s + int((e - s) / 2)
""" A recursive function that constructs
Segment Tree for array[ss..se].
si -. Index of current node in the
segment tree. Initially 0 is
passed as root is always
at index 0.
ss & se -. Starting and ending indexes
of the segment represented by
current node, i.e., st[index]
"""
def constructSTUtil(si, ss, se):
if (ss == se):
# If there is one element
# in array
tree[si] = arr[ss]
return
# If there are more than one elements,
# then recur for left and right subtrees
# and store the sum of the two
# values in this node
else:
mid = getMid(ss, se)
constructSTUtil(2 * si + 1, ss, mid)
constructSTUtil(2 * si + 2, mid + 1, se)
tree[si] = tree[2 * si + 1] + tree[2 * si + 2]
""" A recursive function to update the
nodes which have the given index
in their range.
si -. Index of current node in the segment tree.
Initially 0 is passed as root is always
at index 0.
ss & se -. Starting and ending indexes of the
segment represented by current node,
i.e., st[index]
ind -. Index of array to be updated
val -. The new value to be updated
"""
def updateValueUtil(si, ss, se, idx, val):
# Leaf node
if (ss == se):
tree[si] = tree[si] - arr[idx] + val
arr[idx] = val
else:
mid = getMid(ss, se)
# If idx is in the left child,
# recurse on the left child
if (ss <= idx and idx <= mid):
updateValueUtil(2 * si + 1, ss, mid, idx, val)
# If idx is in the right child,
# recurse on the right child
else:
updateValueUtil(2 * si + 2, mid + 1, se, idx, val)
# Internal node will have the sum
# of both of its children
tree[si] = tree[2 * si + 1] + tree[2 * si + 2]
""" A recursive function to get the number
of Powerful numbers in a given
range of array indexes
si -. Index of current node in the segment tree.
Initially 0 is passed as root is always
at index 0.
ss & se -. Starting and ending indexes of the
segment represented by current node,
i.e., st[index]
l & r -. Starting and ending indexes of
query range
"""
def queryPowerfulUtil(si, ss, se, l, r):
# If segment of this node is
# outside the given range
if (r < ss or se < l):
return 0
# If segment of this node is a part
# of given range, then return the
# number of composites
# in the segment
if (l <= ss and se <= r):
return tree[si]
# If a part of this segment
# overlaps with the given range
mid = getMid(ss, se)
p1 = queryPowerfulUtil(2 * si + 1, ss, mid, l, r)
p2 = queryPowerfulUtil(2 * si + 2, mid + 1, se, l, r)
return (p1 + p2)
def queryPowerful(n, l, r):
print("Number of Powerful numbers between", l, "to", r, "=", queryPowerfulUtil(0, 0, n - 1, l, r))
def updateValue(n, ind, val):
# If val is a Powerful number
# we will update 1 in tree
if (powerful[val]):
updateValueUtil(0, 0, n - 1, ind, 1)
else:
updateValueUtil(0, 0, n - 1, ind, 0)
def precomputePowerful():
for i in range(MAX + 1):
powerful[i] = False
# Computing all Powerful
# numbers till MAX
for i in range(1, MAX + 1):
# If the number is
# Powerful make
# powerful[i] = true
if (isPowerful(i)):
powerful[i] = True
# Precompute all the powerful
# numbers till MAX
precomputePowerful()
# Input array
Input = [ 4, 5, 18, 27, 40, 144 ]
# Size of Input array
n = len(Input)
# Build the array.
BuildArray(Input, n)
# Build segment tree from
# given array
constructSTUtil(0, 0, n - 1)
# Query 1: Query(L = 0, R = 3)
l, r = 0, 3
queryPowerful(n, l, r)
# Query 2: Update(i = 1, x = 9),
# i.e Update input[i] to x
i = 1
val = 9
updateValue(n, i, val)
# Query 3: Query(L = 0, R = 3)
queryPowerful(n, l, r)
# This code is contributed by divyesh072019.