Open in App
Not now

# Count primorials in the given range of Array when updating is allowed

• Last Updated : 05 Dec, 2022

Given an array consisting of N positive integers, and Q queries where each query is one of the following types:

1. 1 l r – Requires printing the count of primorials in the range of indices [l, r].
2. 2 p x –  Need to assign a value x at a given index p.

Examples:

Input: arr[] = {25, 2, 7, 30, 1}  queries = { {1, 1, 4 }, {2, 2, 6}, {1, 0, 3} }
Output:  2 3
Explanation: In the first query, find primorials from the index [1, 4 ].
So for indices in range [1, 4 ] only 2 and 30. These two elements are primorials because 2
is the first prime number and 30= 2*3*5 (product of first three prime numbers).
So the output is 2 for this query.
In the second query, assign a value=6 at index 2. Now array will look like: { 25, 2, 6, 30, 1}.
In the third query, there are 3 integers which are primorials in the range [0, 3] i.e.{2, 6, 30}. So the output is 3.

Input: arr[] = {210, 2, 6, 30, 2310}, queries = { {1, 2, 4}, {1, 0, 4}}
Output: 3 5
Explanation: All elements in the above array are primorial.
210  = 2*3*5*7
2310 = 2*3*5*7*11

Naive approach: The basic approach is to store prime numbers in ascending order using the sieve method. Then for each query of the first type check all the elements in that range and find the count of primorials and for 2nd type of query, assign that value to the given index.

Follow the steps below to find if a number is primorial or not:

• Start from the first prime number stored.
• Keep multiplying these stored prime numbers.
• If at any point product of primes becomes equal to arr[i], then arr[i] is a primorial.
• If the product exceeds arr[i], then arr[i] is not a primorial.

Follow the illustration below to have a better understanding of how to find a primorial

Illustration:

To check arr[i]= 6 is primorial or not. initialize cur with first prime number.
cur = 2;
cur = cur * 3, so now cur has value 6 and arr[ i ] = 6. So arr[ i ] is primorial.

To check arr[i]= 10, is primorial or not. Initialize cur with the first prime 2.
cur = 2;
cur = cur * 3, so now cur has value 6
cur = cur * 5 = 6 * 5 = 30.
Now cur has value 30 and  30 is greater than arr[i].
So arr[i] = 10 is not a primorial.

Time Complexity: O(Q * N)
Auxiliary Space: O(1)

Efficient Approach: This problem can be solved more efficiently by solving the queries in less time using a segment tree based on the following observation:

Mark the primorials present in the array and store them in a data structure such that we can get the count of the primorials within a range of indices and update the values when needed in optimal time.
This task can be done by usage of the segment tree data structure.

Follow the below procedure to implement the segment tree data structure.

• Store the first 15 primorials in ( because the 15th primorial is in order of 1017
• Mark the array elements which are primorial.
• In the segment tree, the leaf nodes store if the corresponding element of the array is primorial or not (stores 1 if primorial; otherwise stores 0) and the internal nodes store how many primorials are there in that given range (i.e. they store the sum of its child nodes).

The following is the segment tree for the given example arr[ ] = {25, 2, 7, 30, 1}:
(cnt represents the count of primorials corresponding to the range covered by that node )

For the query of type 2, if the assigned value x is primorial then store 1 corresponding to that leaf node otherwise store 0. Then update the internal nodes till the root of the segment tree. This will update the counts for the ranges.

Follow the steps mentioned below to implement the approach:

Below is the implementation of the above approach.

## C++

 `// C++ code to count primorials` `// in the given range for Q queries`   `#include ` `using` `namespace` `std;` `const` `int` `mxx = 1e6 + 3;` `vector<``bool``> isPrime(1000, ``true``);` `int` `segment[4 * mxx];` `unordered_map<``long` `long``, ``int``> primorial;`   `// Mark true all prime numbers` `void` `sieve()` `{` `    ``isPrime[0] = isPrime[1] = ``false``;` `    ``for` `(``int` `i = 2; i < 1000; i++) {` `        ``if` `(isPrime[i]) {` `            ``for` `(``int` `j = 2 * i; j < 1000;` `                 ``j = j + i)` `                ``// Mark false which are the` `                ``// multiple of prime numbers` `                ``isPrime[j] = ``false``;` `        ``}` `    ``}` `}`   `// Store primorials` `void` `store_primorials()` `{` `    ``int` `cnt = 0;` `    ``long` `long` `product = 1;` `    ``for` `(``int` `i = 2; i < mxx && cnt < 15;` `         ``i++) {` `        ``if` `(isPrime[i]) {` `            ``product = product * 1LL * i;` `            ``primorial[product]++;` `            ``cnt++;` `        ``}` `    ``}` `}`   `// To build segment tree` `void` `build(``int` `arr[], ``int` `low, ``int` `high,` `           ``int` `ind)` `{` `    ``// The node is leaf node` `    ``if` `(low == high) {` `        ``// If array value is primorial` `        ``// assign leaf node value 1` `        ``// otherwise 0` `        ``auto` `it = primorial.find(arr[low]);` `        ``if` `(it != primorial.end())` `            ``segment[ind] = 1;` `        ``else` `            ``segment[ind] = 0;` `        ``return``;` `    ``}`   `    ``int` `mid = (low + high) >> 1;` `    ``// Go to the left and right child of` `    ``// current node` `    ``build(arr, low, mid, 2 * ind + 1);` `    ``build(arr, mid + 1, high, 2 * ind + 2);`   `    ``// Calculate count of primorials for` `    ``// internal node of segment tree for` `    ``// corresponding ranges`   `    ``segment[ind]` `        ``= segment[2 * ind + 1]` `          ``+ segment[2 * ind + 2];` `}`   `// To update segment tree nodes` `void` `update(``int` `low, ``int` `high, ``int` `ind,` `            ``int` `pos, ``int` `val)` `{` `    ``if` `(low == high) {` `        ``// If new assign value is primorial` `        ``// then mark it 1 otherwise 0` `        ``auto` `it = primorial.find(val);` `        ``if` `(it != primorial.end())` `            ``segment[ind] = 1;` `        ``else` `            ``segment[ind] = 0;` `        ``return``;` `    ``}`   `    ``int` `mid = (low + high) >> 1;`   `    ``// Go to the left child if pos is on` `    ``// the left side of current node` `    ``if` `(pos >= low && pos <= mid)` `        ``update(low, mid, 2 * ind + 1,` `               ``pos, val);` `    ``// Go to the right child if pos is on` `    ``// the right side` `    ``else` `        ``update(mid + 1, high, 2 * ind + 2,` `               ``pos, val);`   `    ``// Update all internal nodes of segment` `    ``// tree` `    ``segment[ind]` `        ``= segment[2 * ind + 1]` `          ``+ segment[2 * ind + 2];` `}`   `// To compute answer for given range l to r` `int` `range_queries(``int` `l, ``int` `r, ``int` `low,` `                  ``int` `high, ``int` `ind)` `{` `    ``// [l, r] is given range, [low, high] is` `    ``// current range if current range is` `    ``// invalid return 0` `    ``if` `(high < l || low > r)` `        ``return` `0;`   `    ``// If current range is completely inside of` `    ``// the given range then return value of` `    ``// that node` `    ``if` `(low >= l && high <= r)` `        ``return` `segment[ind];`   `    ``int` `mid = (low + high) >> 1;` `    ``// Go to the left child and right child` `    ``// to compute answer` `    ``return` `(` `        ``range_queries(l, r, low, mid,` `                      ``2 * ind + 1)` `        ``+ range_queries(l, r, mid + 1, high,` `                        ``2 * ind + 2));` `}`   `// Function to find the count of primorials` `vector<``int``> count(``int` `arr[], ``int` `N,` `                  ``vector >& queries)` `{` `    ``vector<``int``> ans;`   `    ``// Mark prime numbers as a true` `    ``sieve();` `    ``// To precompute primorials` `    ``store_primorials();`   `    ``// Build segment tree for given array` `    ``build(arr, 0, N - 1, 0);`   `    ``for` `(``int` `i = 0; i < queries.size(); i++) {` `        ``if` `(queries[i][0] == 1) {` `            ``int` `l = queries[i][1];` `            ``int` `r = queries[i][2];` `            ``int` `x = range_queries(l, r, 0,` `                                  ``N - 1, 0);` `            ``ans.push_back(x);` `        ``}` `        ``else` `{` `            ``update(0, N - 1, 0, queries[i][1],` `                   ``queries[i][2]);` `        ``}` `    ``}` `    ``return` `ans;` `}`   `// Driver Code` `int` `main()` `{` `    ``// Consider 0 based indexing` `    ``int` `arr[] = { 25, 2, 7, 30, 1 };` `    ``int` `N = ``sizeof``(arr) / ``sizeof``(arr[0]);` `    ``vector > queries{ { 1, 1, 4 },` `                                  ``{ 2, 2, 6 },` `                                  ``{ 1, 0, 3 } };`   `    ``vector<``int``> ans = count(arr, N, queries);` `    ``for` `(``int` `x : ans)` `        ``cout << x << ``" "``;` `    ``return` `0;` `}`

## Python3

 `# python3 code to count primorials` `# in the given range for Q queries` `mxx ``=` `int``(``1e6` `+` `3``)` `isPrime ``=` `[``True` `for` `_ ``in` `range``(``1000``)]` `segment ``=` `[``0` `for` `_ ``in` `range``(``4` `*` `mxx)]` `primorial ``=` `{}`   `# Mark true all prime numbers` `def` `sieve():` `    ``global` `mxx, isprime, segment, primorial` `    ``isPrime[``0``] ``=` `isPrime[``1``] ``=` `False` `    ``for` `i ``in` `range``(``2``, ``1000``):` `        ``if` `(isPrime[i]):` `            ``for` `j ``in` `range``(``2``*``i, ``1000``, i):` `              `  `                ``# Mark false which are the` `                ``# multiple of prime numbers` `                ``isPrime[j] ``=` `False`   `# Store primorials` `def` `store_primorials():`   `    ``global` `mxx, isprime, segment, primorial` `    ``cnt ``=` `0` `    ``product ``=` `1` `    ``for` `i ``in` `range``(``2``, mxx):` `        ``if` `cnt >``=` `15``:` `            ``break`   `        ``if` `(isPrime[i]):` `            ``product ``=` `product ``*` `i` `            ``primorial[product] ``=` `primorial[product] ``+` `\` `                ``1` `if` `product ``in` `primorial ``else` `1` `            ``cnt ``+``=` `1`   `# To build segment tree` `def` `build(arr, low, high, ind):` `    ``global` `mxx, isprime, segment, primorial` `    `  `    ``# The node is leaf node` `    ``if` `(low ``=``=` `high):` `      `  `        ``# If array value is primorial` `        ``# assign leaf node value 1` `        ``# otherwise 0`   `        ``if` `(arr[low] ``in` `primorial):` `            ``segment[ind] ``=` `1` `        ``else``:` `            ``segment[ind] ``=` `0` `        ``return`   `    ``mid ``=` `(low ``+` `high) >> ``1` `    `  `    ``# Go to the left and right child of` `    ``# current node` `    ``build(arr, low, mid, ``2` `*` `ind ``+` `1``)` `    ``build(arr, mid ``+` `1``, high, ``2` `*` `ind ``+` `2``)`   `    ``# Calculate count of primorials for` `    ``# internal node of segment tree for` `    ``# corresponding ranges` `    ``segment[ind] ``=` `segment[``2` `*` `ind ``+` `1``] ``+` `segment[``2` `*` `ind ``+` `2``]`   `# To update segment tree nodes` `def` `update(low, high, ind, pos, val):` `    ``global` `mxx, isprime, segment, primorial` `    ``if` `(low ``=``=` `high):` `      `  `        ``# If new assign value is primorial` `        ``# then mark it 1 otherwise 0` `        ``if` `(val ``in` `primorial):` `            ``segment[ind] ``=` `1` `        ``else``:` `            ``segment[ind] ``=` `0` `        ``return`   `    ``mid ``=` `(low ``+` `high) >> ``1`   `    ``# Go to the left child if pos is on` `    ``# the left side of current node` `    ``if` `(pos >``=` `low ``and` `pos <``=` `mid):` `        ``update(low, mid, ``2` `*` `ind ``+` `1``,` `               ``pos, val)` `        `  `    ``# Go to the right child if pos is on` `    ``# the right side` `    ``else``:` `        ``update(mid ``+` `1``, high, ``2` `*` `ind ``+` `2``,` `               ``pos, val)`   `    ``# Update all internal nodes of segment` `    ``# tree` `    ``segment[ind] ``=` `segment[``2` `*` `ind ``+` `1``] ``+` `segment[``2` `*` `ind ``+` `2``]`   `# To compute answer for given range l to r` `def` `range_queries(l, r, low, high, ind):` `    ``global` `mxx, isprime, segment, primorial` `    `  `    ``# [l, r] is given range, [low, high] is` `    ``# current range if current range is` `    ``# invalid return 0` `    ``if` `(high < l ``or` `low > r):` `        ``return` `0`   `    ``# If current range is completely inside of` `    ``# the given range then return value of` `    ``# that node` `    ``if` `(low >``=` `l ``and` `high <``=` `r):` `        ``return` `segment[ind]`   `    ``mid ``=` `(low ``+` `high) >> ``1` `    `  `    ``# Go to the left child and right child` `    ``# to compute answer` `    ``return` `(` `        ``range_queries(l, r, low, mid,` `                      ``2` `*` `ind ``+` `1``)` `        ``+` `range_queries(l, r, mid ``+` `1``, high,` `                        ``2` `*` `ind ``+` `2``))`   `# Function to find the count of primorials` `def` `count(arr, N, queries):` `    ``global` `mxx, isprime, segment, primorial` `    ``ans ``=` `[]`   `    ``# Mark prime numbers as a true` `    ``sieve()` `    `  `    ``# To precompute primorials` `    ``store_primorials()`   `    ``# Build segment tree for given array` `    ``build(arr, ``0``, N ``-` `1``, ``0``)`   `    ``for` `i ``in` `range``(``0``, ``len``(queries)):` `        ``if` `(queries[i][``0``] ``=``=` `1``):` `            ``l ``=` `queries[i][``1``]` `            ``r ``=` `queries[i][``2``]` `            ``x ``=` `range_queries(l, r, ``0``,` `                              ``N ``-` `1``, ``0``)` `            ``ans.append(x)`   `        ``else``:` `            ``update(``0``, N ``-` `1``, ``0``, queries[i][``1``],` `                   ``queries[i][``2``])`   `    ``return` `ans`   `# Driver Code` `if` `__name__ ``=``=` `"__main__"``:`   `    ``# Consider 0 based indexing` `    ``arr ``=` `[``25``, ``2``, ``7``, ``30``, ``1``]` `    ``N ``=` `len``(arr)` `    ``queries ``=` `[[``1``, ``1``, ``4``], [``2``, ``2``, ``6``], [``1``, ``0``, ``3``]]`   `    ``ans ``=` `count(arr, N, queries)` `    ``for` `x ``in` `ans:` `        ``print``(x, end``=``" "``)`   `    ``# This code is contributed by rakeshsahni`

## Javascript

 ``

Output

`2 3 `

Time Complexity: O(Q * log(N))
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up
Related Articles