Array Range Queries to count Powerful numbers with updates
Given an array of N integers, the task is to perform the following two operations on the given array:
query(L, R): Print the number of Powerful numbers in the subarray from L to R.
update(i, x) : update the value at index i to x, i.e arr[i] = x
A number N is said to be Powerful Number if, for every prime factor p of it, p2 also divides it.
Prerequisites: Powerful Number, Segment tree
Examples:
Input:
arr = {1, 12, 3, 8, 17, 9}
Query 1: query(L = 1, R = 4)
Query 2: update(i = 1, x = 9)
Query 3: query(L = 1, R = 4)
Output:
1
2
Explanation:
Query 1: Powerful numbers in range arr[1:4] is 8.
Query 2: Powerful numbers in range arr[1:4] after update operation is 9 and 8.
Approach:
Since we need to handle point updates and range queries so we will use a segment tree to solve the problem.
- We will precompute all the Powerful numbers till the maximum value that arr[i] can take, say MAX.
The time complexity of this operation will be O(MAX * sqrt(MAX))
- Building the segment tree:
- The problem can be reduced to subarray sum using segment tree.
- Now we can build the segment tree where the leaf nodes will represent 1(when a number is a Powerful number) or 0(when a number is not a powerful number). All the internal nodes will have the sum of both of its children.
- The problem can be reduced to subarray sum using segment tree.
- Point Updates:
- To update an element we need to look at the interval in which the element is and recurse accordingly on the left or the right child. If the element to be updated is a Powerful number then we update the leaf as 1, else 0.
- To update an element we need to look at the interval in which the element is and recurse accordingly on the left or the right child. If the element to be updated is a Powerful number then we update the leaf as 1, else 0.
- Range Query:
- Whenever we get a query from L to R, then we can query the segment tree for the sum of nodes in range L to R, which in turn represents the number of Powerful numbers in the range L to R.
- Whenever we get a query from L to R, then we can query the segment tree for the sum of nodes in range L to R, which in turn represents the number of Powerful numbers in the range L to R.
Below is the implementation of the above approach:
C++
// C++ Program to find the number // of Powerful numbers in subarray // using segment tree #include <bits/stdc++.h> using namespace std; #define MAX 100000 // Size of segment tree = 2^{log(MAX)+1} int tree[3 * MAX]; int arr[MAX]; bool powerful[MAX + 1]; // Function to check if the // number is powerful bool isPowerful( int n) { // First divide the number // repeatedly by 2 while (n % 2 == 0) { int power = 0; while (n % 2 == 0) { n /= 2; power++; } // 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 ( int factor = 3; factor <= sqrt (n); factor += 2) { // Find highest power of // "factor" that divides n int power = 0; while (n % factor == 0) { n = n / factor; power++; } // 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 numenr. Since prime // numbers are not powerful, // we return false if n is not 1. return (n == 1); } // Function to build the array void BuildArray( int input[], int n) { for ( int i = 0; i < n; i++) { // 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. int getMid( int s, int e) { return s + (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] */ void constructSTUtil( int si, int ss, int 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 { int 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 */ void updateValueUtil( int si, int ss, int se, int idx, int val) { // Leaf node if (ss == se) { tree[si] = tree[si] - arr[idx] + val; arr[idx] = val; } else { int 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 */ int queryPowerfulUtil( int si, int ss, int se, int l, int 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 int mid = getMid(ss, se); int p1 = queryPowerfulUtil(2 * si + 1, ss, mid, l, r); int p2 = queryPowerfulUtil(2 * si + 2, mid + 1, se, l, r); return (p1 + p2); } void queryPowerful( int n, int l, int r) { printf ( "Number of Powerful numbers between %d to %d = %d\n" , l, r, queryPowerfulUtil(0, 0, n - 1, l, r)); } void updateValue( int n, int ind, int 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); } void precomputePowerful() { memset (powerful, false , sizeof (powerful)); // Computing all Powerful // numbers till MAX for ( int i = 1; i <= MAX; i++) { // If the number is // Powerful make // powerful[i] = true if (isPowerful(i)) powerful[i] = true ; } } // Driver Code int main() { // Precompute all the powerful // numbers till MAX precomputePowerful(); // Input array int input[] = { 4, 5, 18, 27, 40, 144 }; // Size of Input array int n = sizeof (input) / sizeof (input[0]); // Build the array. BuildArray(input, n); // Build segment tree from // given array constructSTUtil(0, 0, n - 1); // Query 1: Query(L = 0, R = 3) int l = 0, r = 3; queryPowerful(n, l, r); // Query 2: Update(i = 1, x = 9), // i.e Update input[i] to x int i = 1; int val = 9; updateValue(n, i, val); // Query 3: Query(L = 0, R = 3) queryPowerful(n, l, r); return 0; } |
Java
// Java program to find the number // of Powerful numbers in subarray // using segment tree import java.util.*; class GFG{ static final int MAX = 100000 ; // Size of segment tree = 2^{log(MAX)+1} static int []tree = new int [ 3 * MAX]; static int []arr = new int [MAX]; static boolean []powerful = new boolean [MAX + 1 ]; // Function to check if the // number is powerful static boolean isPowerful( int n) { // First divide the number // repeatedly by 2 while (n % 2 == 0 ) { int power = 0 ; while (n % 2 == 0 ) { n /= 2 ; power++; } // 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 ( int factor = 3 ; factor <= Math.sqrt(n); factor += 2 ) { // Find highest power of // "factor" that divides n int power = 0 ; while (n % factor == 0 ) { n = n / factor; power++; } // 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 numenr. Since prime // numbers are not powerful, // we return false if n is not 1. return (n == 1 ); } // Function to build the array static void BuildArray( int input[], int n) { for ( int i = 0 ; i < n; i++) { // 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. static int getMid( int s, int e) { return s + (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] */ static void constructSTUtil( int si, int ss, int 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 { int 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 */ static void updateValueUtil( int si, int ss, int se, int idx, int val) { // Leaf node if (ss == se) { tree[si] = tree[si] - arr[idx] + val; arr[idx] = val; } else { int mid = getMid(ss, se); // If idx is in the left child, // recurse on the left child if (ss <= idx && 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 */ static int queryPowerfulUtil( int si, int ss, int se, int l, int r) { // If segment of this node is // outside the given range if (r < ss || 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 && se <= r) { return tree[si]; } // If a part of this segment // overlaps with the given range int mid = getMid(ss, se); int p1 = queryPowerfulUtil( 2 * si + 1 , ss, mid, l, r); int p2 = queryPowerfulUtil( 2 * si + 2 , mid + 1 , se, l, r); return (p1 + p2); } static void queryPowerful( int n, int l, int r) { System.out.printf( "Number of Powerful numbers " + "between %d to %d = %d\n" , l, r, queryPowerfulUtil( 0 , 0 , n - 1 , l, r)); } static void updateValue( int n, int ind, int 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 ); } static void precomputePowerful() { Arrays.fill(powerful, false ); // Computing all Powerful // numbers till MAX for ( int i = 1 ; i <= MAX; i++) { // If the number is // Powerful make // powerful[i] = true if (isPowerful(i)) powerful[i] = true ; } } // Driver Code public static void main(String[] args) { // Precompute all the powerful // numbers till MAX precomputePowerful(); // Input array int input[] = { 4 , 5 , 18 , 27 , 40 , 144 }; // Size of Input array int n = input.length; // Build the array. BuildArray(input, n); // Build segment tree from // given array constructSTUtil( 0 , 0 , n - 1 ); // Query 1: Query(L = 0, R = 3) int l = 0 , r = 3 ; queryPowerful(n, l, r); // Query 2: Update(i = 1, x = 9), // i.e Update input[i] to x int i = 1 ; int val = 9 ; updateValue(n, i, val); // Query 3: Query(L = 0, R = 3) queryPowerful(n, l, r); } } // This code is contributed by amal kumar choubey |
Python3
# 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. |
C#
// C# program to find the number // of Powerful numbers in subarray // using segment tree using System; class GFG{ static readonly int MAX = 100000; // Size of segment tree = 2^{log(MAX)+1} static int []tree = new int [3 * MAX]; static int []arr = new int [MAX]; static bool []powerful = new bool [MAX + 1]; // Function to check if the // number is powerful static bool isPowerful( int n) { // First divide the number // repeatedly by 2 while (n % 2 == 0) { int power = 0; while (n % 2 == 0) { n /= 2; power++; } // 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 ( int factor = 3; factor <= Math.Sqrt(n); factor += 2) { // Find highest power of // "factor" that divides n int power = 0; while (n % factor == 0) { n = n / factor; power++; } // 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 numenr. Since prime // numbers are not powerful, // we return false if n is not 1. return (n == 1); } // Function to build the array static void BuildArray( int []input, int n) { for ( int i = 0; i < n; i++) { // 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. static int getMid( int s, int e) { return s + (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] */ static void constructSTUtil( int si, int ss, int 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 { int 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 */ static void updateValueUtil( int si, int ss, int se, int idx, int val) { // Leaf node if (ss == se) { tree[si] = tree[si] - arr[idx] + val; arr[idx] = val; } else { int mid = getMid(ss, se); // If idx is in the left child, // recurse on the left child if (ss <= idx && 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 */ static int queryPowerfulUtil( int si, int ss, int se, int l, int r) { // If segment of this node is // outside the given range if (r < ss || 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 && se <= r) { return tree[si]; } // If a part of this segment // overlaps with the given range int mid = getMid(ss, se); int p1 = queryPowerfulUtil(2 * si + 1, ss, mid, l, r); int p2 = queryPowerfulUtil(2 * si + 2, mid + 1, se, l, r); return (p1 + p2); } static void queryPowerful( int n, int l, int r) { Console.WriteLine( "Number of Powerful numbers " + "between " + l + " to " +r+ " = " + queryPowerfulUtil(0, 0, n - 1, l, r)); } static void updateValue( int n, int ind, int 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); } static void precomputePowerful() { for ( int i = 0; i <= MAX; i++) powerful[i] = false ; // Computing all Powerful // numbers till MAX for ( int i = 1; i <= MAX; i++) { // If the number is // Powerful make // powerful[i] = true if (isPowerful(i)) powerful[i] = true ; } } // Driver Code public static void Main(String[] args) { // Precompute all the powerful // numbers till MAX precomputePowerful(); // Input array int []input = { 4, 5, 18, 27, 40, 144 }; // Size of Input array int n = input.Length; // Build the array. BuildArray(input, n); // Build segment tree from // given array constructSTUtil(0, 0, n - 1); // Query 1: Query(L = 0, R = 3) int l = 0, r = 3; queryPowerful(n, l, r); // Query 2: Update(i = 1, x = 9), // i.e Update input[i] to x int i = 1; int val = 9; updateValue(n, i, val); // Query 3: Query(L = 0, R = 3) queryPowerful(n, l, r); } } // This code is contributed by Rohit_ranjan |
Javascript
<script> // JavaScript program to find the number // of Powerful numbers in subarray // using segment tree let MAX = 100000; // Size of segment tree = 2^{log(MAX)+1} let tree = new Array(3 * MAX); let arr = new Array(MAX); let powerful = new Array(MAX + 1); // Function to check if the // number is powerful function isPowerful(n) { // First divide the number // repeatedly by 2 while (n % 2 == 0) { let power = 0; while (n % 2 == 0) { n = parseInt(n / 2, 10); power++; } // 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 (let factor = 3; factor <= Math.sqrt(n); factor += 2) { // Find highest power of // "factor" that divides n let power = 0; while (n % factor == 0) { n = parseInt(n / factor, 10); power++; } // 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 numenr. Since prime // numbers are not powerful, // we return false if n is not 1. return (n == 1); } // Function to build the array function BuildArray(input, n) { for (let i = 0; i < n; i++) { // 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. function getMid(s, e) { return s + parseInt((e - s) / 2, 10); } /* 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] */ function 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 { let 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 */ function updateValueUtil(si, ss, se, idx, val) { // Leaf node if (ss == se) { tree[si] = tree[si] - arr[idx] + val; arr[idx] = val; } else { let mid = getMid(ss, se); // If idx is in the left child, // recurse on the left child if (ss <= idx && 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 */ function queryPowerfulUtil(si, ss, se, l, r) { // If segment of this node is // outside the given range if (r < ss || 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 && se <= r) { return tree[si]; } // If a part of this segment // overlaps with the given range let mid = getMid(ss, se); let p1 = queryPowerfulUtil(2 * si + 1, ss, mid, l, r); let p2 = queryPowerfulUtil(2 * si + 2, mid + 1, se, l, r); return (p1 + p2); } function queryPowerful(n, l, r) { document.write( "Number of Powerful numbers " + "between " + l + " to " +r+ " = " + queryPowerfulUtil(0, 0, n - 1, l, r) + "</br>" ); } function 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); } function precomputePowerful() { for (let i = 0; i <= MAX; i++) powerful[i] = false ; // Computing all Powerful // numbers till MAX for (let i = 1; i <= MAX; i++) { // 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 let input = [ 4, 5, 18, 27, 40, 144 ]; // Size of Input array let n = input.length; // Build the array. BuildArray(input, n); // Build segment tree from // given array constructSTUtil(0, 0, n - 1); // Query 1: Query(L = 0, R = 3) let l = 0, r = 3; queryPowerful(n, l, r); // Query 2: Update(i = 1, x = 9), // i.e Update input[i] to x let i = 1; let val = 9; updateValue(n, i, val); // Query 3: Query(L = 0, R = 3) queryPowerful(n, l, r); </script> |
Number of Powerful numbers between 0 to 3 = 2 Number of Powerful numbers between 0 to 3 = 3
Time Complexity: O(logN) per query
Please Login to comment...