Number of primes in a subarray (with updates) (original) (raw)

Last Updated : 11 Jul, 2025

You are given an array**arr[]** of size n. Your task is to process **q**queries, each consisting of three integers, of the following two types:

  1. [1, l, r]: Find the number of prime numbers in the subarray arr[l…r] (inclusive).
  2. [2, i, x]: Update the element at index i to x(i.e., set arr[i] = x).

**Examples:

**Input: _n = 6, q = 3
_arr[] = [1, 2, 3, 5, 7, 9]
_queries[][] = [ [1, 0, 4], [2, 3, 6], [1, 0, 4] ]
**Output: _4 3
**Explanation: _For the query 1, the number of primes in range [0, 4] are 4 (2, 3, 5, 7).
_For the query 2, after an update, the array becomes [1, 2, 3, 6, 7, 9].
_For the query 3, the number of primes in range [0, 4] are 3 (2, 3, 7).

[Naive Approach] - Check all Numbers One by One

The idea is to treat each query as either a prime-counting operation over a subarray or an update to a single element. For a counting query, we scan through the specified range [L, R], use trial division to test each element for primality, and keep a running total of how many primes we encounter. For an update query, we simply overwrite the array at the given index with the new value.

**Time Complexity Analysis: For every query, we need to consider all numbers in the range and for every number, we need to check if it is prime. An upper bound on time complexity is O(q n sqrt(MAX)), Here MAX is the maximum element in range and a range may have at most n elements.

Below is given the **implementation:

C++ `

#include <bits/stdc++.h> using namespace std;

// Function to check if a number is prime bool isPrime(int n) { if(n <= 1) return false; for(int i = 2; i * i <= n; i++) { if(n % i == 0) return false; } return true; }

vector solveQueries(vector &arr, vector<vector> &queries) { int n = arr.size();

// to store the result of query of type 1
vector<int> res;

// process all the queries
for(auto query: queries) {

    // to find the maximum 
    // product in the range [L, R]
    if(query[0] == 1) {
        int l = query[1];
        int r = query[2];
        int cnt = 0;

        // find all primes in the range [L, R]
        for(int i = l; i <= r; i++) {
            if(isPrime(arr[i])) {
                cnt++;
            }
        }

        res.push_back(cnt);
    }

    // else update the value of arr[i]
    else if(query[0] == 2) {
        int i = query[1];
        int x = query[2];
        arr[i] = x;
    }
}

return res;

}

int main() { vector arr = {1, 2, 3, 5, 7, 9}; vector<vector> queries = { {1, 0, 4}, {2, 3, 6}, {1, 0, 4}}; vector res = solveQueries(arr, queries); for(auto i:res) { cout << i << " "; } return 0; }

Java

import java.util.*;

public class GfG {

// Function to check if a number is prime
public static boolean isPrime(int n) {
    if(n <= 1) return false;
    for(int i = 2; i * i <= n; i++) {
        if(n % i == 0) return false;
    }
    return true;
}

public static List<Integer> solveQueries(List<Integer> arr, 
            List<List<Integer>> queries) {
    int n = arr.size();

    
    // to store the result of query of type 1
    List<Integer> res = new ArrayList<>();

    
    // process all the queries
    for(List<Integer> query: queries) {

        
        // to find the maximum 
        // product in the range [L, R]
        if(query.get(0) == 1) {
            int l = query.get(1);
            int r = query.get(2);
            int cnt = 0;

            
            // find all primes in the range [L, R]
            for(int i = l; i <= r; i++) {
                if(isPrime(arr.get(i))) {
                    cnt++;
                }
            }

            res.add(cnt);
        }

        
        // else update the value of arr[i]
        else if(query.get(0) == 2) {
            int i = query.get(1);
            int x = query.get(2);
            arr.set(i, x);
        }
    }

    return res;
}

public static void main(String[] args) {
    List<Integer> arr = Arrays.asList(1, 2, 3, 5, 7, 9);
    List<List<Integer>> queries = Arrays.asList(
        Arrays.asList(1, 0, 4), Arrays.asList(2, 3, 6), 
        Arrays.asList(1, 0, 4));
    List<Integer> res = solveQueries(arr, queries);
    for(int i:res) {
        System.out.print(i + " ");
    }
}

}

Python

Function to check if a number is prime

def isPrime(n): if n <= 1: return False for i in range(2, int(n ** 0.5) + 1): if n % i == 0: return False return True

def solveQueries(arr, queries): n = len(arr)

# to store the result of query of type 1
res = []


# process all the queries
for query in queries:

    
    # to find the maximum 
    # product in the range [L, R]
    if query[0] == 1:
        l = query[1]
        r = query[2]
        cnt = 0

        
        # find all primes in the range [L, R]
        for i in range(l, r + 1):
            if isPrime(arr[i]):
                cnt += 1

        res.append(cnt)

    
    # else update the value of arr[i]
    elif query[0] == 2:
        i = query[1]
        x = query[2]
        arr[i] = x

return res

if name == "main": arr = [1, 2, 3, 5, 7, 9] queries = [ [1, 0, 4], [2, 3, 6], [1, 0, 4] ] res = solveQueries(arr, queries) for i in res: print(i, end=" ")

C#

using System; using System.Collections.Generic;

public class GfG {

// Function to check if a number is prime
public static bool isPrime(int n) {
    if(n <= 1) return false;
    for(int i = 2; i * i <= n; i++) {
        if(n % i == 0) return false;
    }
    return true;
}

public static List<int> solveQueries(List<int> arr, 
            List<List<int>> queries) {
    int n = arr.Count;

    
    // to store the result of query of type 1
    List<int> res = new List<int>();

    
    // process all the queries
    foreach(List<int> query in queries) {

        
        // to find the maximum 
        // product in the range [L, R]
        if(query[0] == 1) {
            int l = query[1];
            int r = query[2];
            int cnt = 0;

            
            // find all primes in the range [L, R]
            for(int i = l; i <= r; i++) {
                if(isPrime(arr[i])) {
                    cnt++;
                }
            }

            res.Add(cnt);
        }

        
        // else update the value of arr[i]
        else if(query[0] == 2) {
            int i = query[1];
            int x = query[2];
            arr[i] = x;
        }
    }

    return res;
}

public static void Main(string[] args) {
    List<int> arr = new List<int> {1, 2, 3, 5, 7, 9};
    List<List<int>> queries = new List<List<int>> {
        new List<int> {1, 0, 4}, 
        new List<int> {2, 3, 6}, new List<int> {1, 0, 4}
    };
    List<int> res = solveQueries(arr, queries);
    foreach(int i in res) {
        Console.Write(i + " ");
    }
}

}

JavaScript

// Function to check if a number is prime function isPrime(n) { if(n <= 1) return false; for(let i = 2; i * i <= n; i++) { if(n % i == 0) return false; } return true; }

function solveQueries(arr, queries) { let n = arr.length;

// to store the result of query of type 1
let res = [];


// process all the queries
for(let query of queries) {

    
    // to find the maximum 
    // product in the range [L, R]
    if(query[0] == 1) {
        let l = query[1];
        let r = query[2];
        let cnt = 0;

        
        // find all primes in the range [L, R]
        for(let i = l; i <= r; i++) {
            if(isPrime(arr[i])) {
                cnt++;
            }
        }

        res.push(cnt);
    }

    
    // else update the value of arr[i]
    else if(query[0] == 2) {
        let i = query[1];
        let x = query[2];
        arr[i] = x;
    }
}

return res;

}

let arr = [1, 2, 3, 5, 7, 9]; let queries = [ [1, 0, 4], [2, 3, 6], [1, 0, 4] ]; let res = solveQueries(arr, queries); for(let i of res) { process.stdout.write(i + " "); }

`

[Better Approach] - Sieve of Eratosthenes

We can use Sieve of Eratosthenes to preprocess all the primes till the maximum value arri can take say MAX in O(MAX log(log(MAX)). After we have built the isPrime array till MAX, we can answer every range query in O(n) time.

[Expected Approach] - Using Segment Tree

We basically reduce the problem to subarray sum using segment tree. Now, we can build the segment tree where a leaf node is represented as either 0 (if it is not a prime number) or 1 (if it is a prime number).
The internal nodes of the segment tree equal to the sum of its child nodes, thus a node represents the total primes in the range from L to R where the range L to R falls under this node and the sub-tree below it.

**Handling Queries and Point Updates: Whenever we get a query from start to end, then we can query the segment tree for the sum of nodes in range start to end, which in turn represent the number of primes in range start to end.

If we need to perform a point update and update the value at index i to x, then we check for the following cases:

If we need to perform a point update and update the value at index i to x, then we check for the following cases:

**Let the old value of arr[i] be y and the new value be x

**Case 1: If x and y both are primes
Count of primes in the subarray does not change so we just update array and do not modify the segment tree

**Case 2: If x and y both are non primes
Count of primes in the subarray does not change so we just update array and do not modify the segment tree

**Case 3: If y is prime but x is non prime
Count of primes in the subarray decreases so we update array and add -1 to every range, the index i which is to be updated, is a part of in the segment tree

**Case 4: If y is non prime but x is prime
Count of primes in the subarray increases so we update array and add 1 to every range, the index i which is to be updated, is a part of in the segment tree

Follow the below given steps:

Below is given the **implementation:

C++ `

#include <bits/stdc++.h> using namespace std;

vector findPrimes(int n) { vector primes(n + 1, 1); primes[0] = 0; primes[1] = 0; for (int i = 2; i * i <= n; i++) { if (primes[i]) { for (int j = i * i; j <= n; j += i) { primes[j] = 0; } } } return primes; }

// 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 to get the number // of primes in a given range int queryPrimesUtil(vector &tree, int ss, int se, int qs, int qe, int index) {

// If segment of this node is a part of given range
// then return the number of primes in the segment
if (qs <= ss && qe >= se)
    return tree[index];

// If segment of this node is outside the given range
if (se < qs || ss > qe)
    return 0;

// If a part of this segment overlaps with the given range
int mid = getMid(ss, se);
return queryPrimesUtil(tree, ss, mid, qs, qe, 2 * index + 1) + 
       queryPrimesUtil(tree, mid + 1, se, qs, qe, 2 * index + 2);

}

// A recursive function to update the nodes // which have the given index in their range. void updateValueUtil(vector &tree, int ss, int se, int i, int diff, int si) {

// Base Case: If the input index lies
// outside the range of this segment
if (i < ss || i > se)
    return;

// If the input index is in range of this node,
// update the value of the node and its children
tree[si] = tree[si] + diff;
if (se != ss) {
    int mid = getMid(ss, se);
    updateValueUtil(tree, ss, mid, i, diff, 2 * si + 1);
    updateValueUtil(tree, mid + 1, se, i, diff, 2 * si + 2);
}

}

// The function to update a value in input array and segment tree. // It uses updateValueUtil() to update the value in segment tree void updateValue(vector &arr, vector &tree, int n, int i, int new_val, vector &primes) {

// Check for erroneous input index
if (i < 0 || i > n - 1) {
    printf("Invalid Input");
    return;
}

int diff, oldValue;

oldValue = arr[i];

// Update the value in array
arr[i] = new_val;

// Case 1: Old and new values both are primes
if (primes[oldValue] && primes[new_val])
    return;

// Case 2: Old and new values both non primes
if ((!primes[oldValue]) && (!primes[new_val]))
    return;

// Case 3: Old value was prime, new value is non prime
if (primes[oldValue] && !primes[new_val]) {
    diff = -1;
}

// Case 4: Old value was non prime, new_val is prime
if (!primes[oldValue] && primes[new_val]) {
    diff = 1;
}

// Update the values of nodes in segment tree
updateValueUtil(tree, 0, n - 1, i, diff, 0);

}

// Return number of primes in range from index qs to qe int queryPrimes(vector &tree, int n, int qs, int qe) { return queryPrimesUtil(tree, 0, n - 1, qs, qe, 0); }

// A recursive function that constructs Segment Tree // for array[ss..se]. int constructSTUtil(vector &arr, int ss, int se, vector &tree, int si, vector &primes) {

// If there is one element in array, check if it
// is prime then store 1 in the segment tree else
// store 0 and return
if (ss == se) {

    // if arr[ss] is prime
    if (primes[arr[ss]]) 
        tree[si] = 1;        
    else 
        tree[si] = 0;
    
    return tree[si];
}

// 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
int mid = getMid(ss, se);
tree[si] = constructSTUtil(arr, ss, mid, tree, si * 2 + 1, primes) + 
    constructSTUtil(arr, mid + 1, se, tree, si * 2 + 2, primes);
return tree[si];

}

//Function to construct segment tree from given array. vector constructST(vector &arr, int n, vector &primes) {

// Height of segment tree
int x = (int)(ceil(log2(n)));

// Maximum size of segment tree
int max_size = 2 * (int)pow(2, x) - 1;

vector<int> tree(max_size);

// Fill the allocated memory tree
constructSTUtil(arr, 0, n - 1, tree, 0, primes);

// Return the constructed segment tree
return tree;

}

vector solveQueries(vector &arr, vector<vector> &queries) { int n = arr.size();

// to store the result of query of type 1
vector<int> res;

vector<int> primes = findPrimes(1000000);

// construct segment tree from given array
vector<int> tree = constructST(arr, n, primes);

// process all the queries
for(auto query: queries) {

    // to find the number of primes in the range [L, R]
    if(query[0] == 1) {
        int l = query[1];
        int r = query[2];
        int cnt = queryPrimes(tree, n, l, r);
        res.push_back(cnt);
    }

    // else update the value of arr[i]
    else if(query[0] == 2) {
        int i = query[1];
        int x = query[2];
        updateValue(arr, tree, n, i, x, primes);
    }
}
return res;

}

int main() { vector arr = {1, 2, 3, 5, 7, 9}; vector<vector> queries = { {1, 0, 4}, {2, 3, 6}, {1, 0, 4}}; vector res = solveQueries(arr, queries); for(auto i:res) { cout << i << " "; } return 0; }

Java

import java.util.*;

public class GfG {

// A utility function to get the 
// middle index from corner indexes.
public static int getMid(int s, int e) {
    return s + (e - s) / 2; 
}


// A recursive function that constructs Segment Tree 
// for array[ss..se].
public static int constructSTUtil(List<Integer> arr, int ss, 
    int se, List<Integer> tree, int si, List<Integer> primes) {

    // If there is one element in array, check if it
    // is prime then store 1 in the segment tree else
    // store 0 and return
    if (ss == se) {

        // if arr.get(ss) is prime
        if (primes.get(arr.get(ss)) == 1) 
            tree.set(si, 1);        
        else 
            tree.set(si, 0);
        
        return tree.get(si);
    }

    // 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
    int mid = getMid(ss, se);
    int left = constructSTUtil(arr, ss, mid, tree, si * 2 + 1, primes);
    int right = constructSTUtil(arr, mid + 1, se, tree, si * 2 + 2, primes);
    tree.set(si, left + right);
    return tree.get(si);
}


//Function to construct segment tree from given array. 
public static List<Integer> constructST(List<Integer> arr, int n, List<Integer> primes) {

    // Height of segment tree
    int x = (int)(Math.ceil(Math.log(n) / Math.log(2)));

    // Maximum size of segment tree
    int max_size = 2 * (int)Math.pow(2, x) - 1;

    List<Integer> tree = new ArrayList<>(Collections.nCopies(max_size, 0));

    // Fill the allocated memory tree
    constructSTUtil(arr, 0, n - 1, tree, 0, primes);

    // Return the constructed segment tree
    return tree;
}


// A recursive function to get the number 
// of primes in a given range
public static int queryPrimesUtil(List<Integer> tree, 
    int ss, int se, int qs, int qe, int index) {

    // If segment of this node is a part of given range
    // then return the number of primes in the segment
    if (qs <= ss && qe >= se)
        return tree.get(index);

    // If segment of this node is outside the given range
    if (se < qs || ss > qe)
        return 0;

    // If a part of this segment overlaps with the given range
    int mid = getMid(ss, se);
    return queryPrimesUtil(tree, ss, mid, qs, qe, 2 * index + 1) + 
           queryPrimesUtil(tree, mid + 1, se, qs, qe, 2 * index + 2);
}


// A recursive function to update the nodes 
// which have the given index in their range.
public static void updateValueUtil(List<Integer> tree, 
    int ss, int se, int i, int diff, int si) {

    // Base Case: If the input index lies
    // outside the range of this segment
    if (i < ss || i > se)
        return;

    // If the input index is in range of this node,
    // update the value of the node and its children
    tree.set(si, tree.get(si) + diff);
    if (se != ss) {
        int mid = getMid(ss, se);
        updateValueUtil(tree, ss, mid, i, diff, 2 * si + 1);
        updateValueUtil(tree, mid + 1, se, i, diff, 2 * si + 2);
    }
}


// The function to update a value in input array and segment tree.
// It uses updateValueUtil() to update the value in segment tree
public static void updateValue(List<Integer> arr, List<Integer> tree, 
    int n, int i, int new_val, List<Integer> primes) {

    // Check for erroneous input index
    if (i < 0 || i > n - 1) {
        System.out.println("Invalid Input");
        return;
    }

    int diff, oldValue;

    oldValue = arr.get(i);

    // Update the value in array
    arr.set(i, new_val);

    // Case 1: Old and new values both are primes
    if (primes.get(oldValue) == 1 && primes.get(new_val) == 1)
        return;

    // Case 2: Old and new values both non primes
    if (primes.get(oldValue) == 0 && primes.get(new_val) == 0)
        return;

    // Case 3: Old value was prime, new value is non prime
    if (primes.get(oldValue) == 1 && primes.get(new_val) == 0) {
        diff = -1;
    }

    // Case 4: Old value was non prime, new_val is prime
    else {
        diff = 1;
    }

    // Update the values of nodes in segment tree
    updateValueUtil(tree, 0, n - 1, i, diff, 0);
}


// Return number of primes in range from index qs to qe
public static int queryPrimes(List<Integer> tree, int n, int qs, int qe) {
    return queryPrimesUtil(tree, 0, n - 1, qs, qe, 0);
}


public static List<Integer> findPrimes(int n) {
    List<Integer> primes = new ArrayList<>(Collections.nCopies(n + 1, 1));
    primes.set(0, 0);
    primes.set(1, 0);
    for (int i = 2; i * i <= n; i++) {
        if (primes.get(i) == 1) {
            for (int j = i * i; j <= n; j += i) {
                primes.set(j, 0);
            }
        }
    }
    return primes;
}


public static List<Integer> solveQueries(List<Integer> arr, 
        List<List<Integer>> queries) {
    int n = arr.size();

    // to store the result of query of type 1
    List<Integer> res = new ArrayList<>();

    List<Integer> primes = findPrimes(1000000);

    // construct segment tree from given array
    List<Integer> tree = constructST(arr, n, primes);

    // process all the queries
    for (List<Integer> query: queries) {

        // to find the number of primes in the range [L, R]
        if (query.get(0) == 1) {
            int l = query.get(1);
            int r = query.get(2);
            int cnt = queryPrimes(tree, n, l, r);
            res.add(cnt);
        }

        // else update the value of arr[i]
        else if (query.get(0) == 2) {
            int i = query.get(1);
            int x = query.get(2);
            updateValue(arr, tree, n, i, x, primes);
        }
    }
    return res;
}


public static void main(String[] args) {
    List<Integer> arr = Arrays.asList(1, 2, 3, 5, 7, 9);
    List<List<Integer>> queries = Arrays.asList(
        Arrays.asList(1, 0, 4), Arrays.asList(2, 3, 6), Arrays.asList(1, 0, 4)
    );
    List<Integer> res = solveQueries(arr, queries);
    for (int i: res) {
        System.out.print(i + " ");
    }
}

}

Python

A utility function to get the

middle index from corner indexes.

def getMid(s, e): return s + (e - s) // 2

A recursive function that constructs Segment Tree

for array[ss..se].

def constructSTUtil(arr, ss, se, tree, si, primes):

# If there is one element in array, check if it
# is prime then store 1 in the segment tree else
# store 0 and return
if ss == se:

    # if arr[ss] is prime
    if primes[arr[ss]] == 1:
        tree[si] = 1        
    else:
        tree[si] = 0
    
    return tree[si]

# 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
mid = getMid(ss, se)
tree[si] = constructSTUtil(arr, ss, mid, tree, si * 2 + 1, primes) + \
           constructSTUtil(arr, mid + 1, se, tree, si * 2 + 2, primes)
return tree[si]

#Function to construct segment tree from given array. def constructST(arr, n, primes):

# Height of segment tree
x = int(math.ceil(math.log(n, 2)))

# Maximum size of segment tree
max_size = 2 * (2 ** x) - 1

tree = [0] * max_size

# Fill the allocated memory tree
constructSTUtil(arr, 0, n - 1, tree, 0, primes)

# Return the constructed segment tree
return tree

A recursive function to get the number

of primes in a given range

def queryPrimesUtil(tree, ss, se, qs, qe, index):

# If segment of this node is a part of given range
# then return the number of primes in the segment
if qs <= ss and qe >= se:
    return tree[index]

# If segment of this node is outside the given range
if se < qs or ss > qe:
    return 0

# If a part of this segment overlaps with the given range
mid = getMid(ss, se)
return queryPrimesUtil(tree, ss, mid, qs, qe, 2 * index + 1) + \
       queryPrimesUtil(tree, mid + 1, se, qs, qe, 2 * index + 2)

A recursive function to update the nodes

which have the given index in their range.

def updateValueUtil(tree, ss, se, i, diff, si):

# Base Case: If the input index lies
# outside the range of this segment
if i < ss or i > se:
    return

# If the input index is in range of this node,
# update the value of the node and its children
tree[si] = tree[si] + diff
if se != ss:
    mid = getMid(ss, se)
    updateValueUtil(tree, ss, mid, i, diff, 2 * si + 1)
    updateValueUtil(tree, mid + 1, se, i, diff, 2 * si + 2)

The function to update a value in input array and segment tree.

It uses updateValueUtil() to update the value in segment tree

def updateValue(arr, tree, n, i, new_val, primes):

# Check for erroneous input index
if i < 0 or i > n - 1:
    print("Invalid Input")
    return

oldValue = arr[i]

# Update the value in array
arr[i] = new_val

# Case 1: Old and new values both are primes
if primes[oldValue] == 1 and primes[new_val] == 1:
    return

# Case 2: Old and new values both non primes
if primes[oldValue] == 0 and primes[new_val] == 0:
    return

# Case 3: Old value was prime, new value is non prime
if primes[oldValue] == 1 and primes[new_val] == 0:
    diff = -1

# Case 4: Old value was non prime, new_val is prime
if primes[oldValue] == 0 and primes[new_val] == 1:
    diff = 1

# Update the values of nodes in segment tree
updateValueUtil(tree, 0, n - 1, i, diff, 0)

Return number of primes in range from index qs to qe

def queryPrimes(tree, n, qs, qe): return queryPrimesUtil(tree, 0, n - 1, qs, qe, 0)

def findPrimes(n): primes = [1] * (n + 1) primes[0] = 0 primes[1] = 0 for i in range(2, int(n ** 0.5) + 1): if primes[i] == 1: for j in range(i * i, n + 1, i): primes[j] = 0 return primes

def solveQueries(arr, queries): n = len(arr)

# to store the result of query of type 1
res = []

primes = findPrimes(1000000)

# construct segment tree from given array
tree = constructST(arr, n, primes)

# process all the queries
for query in queries:

    # to find the number of primes in the range [L, R]
    if query[0] == 1:
        l = query[1]
        r = query[2]
        cnt = queryPrimes(tree, n, l, r)
        res.append(cnt)

    # else update the value of arr[i]
    elif query[0] == 2:
        i = query[1]
        x = query[2]
        updateValue(arr, tree, n, i, x, primes)
return res

if name == "main": import math

arr = [1, 2, 3, 5, 7, 9]
queries = [
    [1, 0, 4], [2, 3, 6], [1, 0, 4]
]
res = solveQueries(arr, queries)
for i in res:
    print(i, end=" ")

C#

using System; using System.Collections.Generic; using System.Linq;

public class GfG {

// A utility function to get the 
// middle index from corner indexes.
public static int getMid(int s, int e) {
    return s + (e - s) / 2; 
}


// A recursive function that constructs Segment Tree 
// for array[ss..se].
public static int constructSTUtil(List<int> arr, int ss, 
    int se, List<int> tree, int si, List<int> primes) {

    // If there is one element in array, check if it
    // is prime then store 1 in the segment tree else
    // store 0 and return
    if (ss == se) {

        // if arr[ss] is prime
        if (primes[arr[ss]] == 1) 
            tree[si] = 1;        
        else 
            tree[si] = 0;
        
        return tree[si];
    }

    // 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
    int mid = getMid(ss, se);
    int left = constructSTUtil(arr, ss, mid, tree, si * 2 + 1, primes);
    int right = constructSTUtil(arr, mid + 1, se, tree, si * 2 + 2, primes);
    tree[si] = left + right;
    return tree[si];
}


//Function to construct segment tree from given array. 
public static List<int> constructST(List<int> arr, int n, List<int> primes) {

    // Height of segment tree
    int x = (int)(Math.Ceiling(Math.Log(n, 2)));

    // Maximum size of segment tree
    int max_size = 2 * (int)Math.Pow(2, x) - 1;

    List<int> tree = Enumerable.Repeat(0, max_size).ToList();

    // Fill the allocated memory tree
    constructSTUtil(arr, 0, n - 1, tree, 0, primes);

    // Return the constructed segment tree
    return tree;
}


// A recursive function to get the number 
// of primes in a given range
public static int queryPrimesUtil(List<int> tree, 
    int ss, int se, int qs, int qe, int index) {

    // If segment of this node is a part of given range
    // then return the number of primes in the segment
    if (qs <= ss && qe >= se)
        return tree[index];

    // If segment of this node is outside the given range
    if (se < qs || ss > qe)
        return 0;

    // If a part of this segment overlaps with the given range
    int mid = getMid(ss, se);
    return queryPrimesUtil(tree, ss, mid, qs, qe, 2 * index + 1) + 
           queryPrimesUtil(tree, mid + 1, se, qs, qe, 2 * index + 2);
}


// A recursive function to update the nodes 
// which have the given index in their range.
public static void updateValueUtil(List<int> tree, 
    int ss, int se, int i, int diff, int si) {

    // Base Case: If the input index lies
    // outside the range of this segment
    if (i < ss || i > se)
        return;

    // If the input index is in range of this node,
    // update the value of the node and its children
    tree[si] = tree[si] + diff;
    if (se != ss) {
        int mid = getMid(ss, se);
        updateValueUtil(tree, ss, mid, i, diff, 2 * si + 1);
        updateValueUtil(tree, mid + 1, se, i, diff, 2 * si + 2);
    }
}


// The function to update a value in input array and segment tree.
// It uses updateValueUtil() to update the value in segment tree
public static void updateValue(List<int> arr, List<int> tree, 
    int n, int i, int new_val, List<int> primes) {

    // Check for erroneous input index
    if (i < 0 || i > n - 1) {
        Console.WriteLine("Invalid Input");
        return;
    }

    int diff, oldValue;

    oldValue = arr[i];

    // Update the value in array
    arr[i] = new_val;

    // Case 1: Old and new values both are primes
    if (primes[oldValue] == 1 && primes[new_val] == 1)
        return;

    // Case 2: Old and new values both non primes
    if (primes[oldValue] == 0 && primes[new_val] == 0)
        return;

    // Case 3: Old value was prime, new value is non prime
    if (primes[oldValue] == 1 && primes[new_val] == 0) {
        diff = -1;
    }

    // Case 4: Old value was non prime, new_val is prime
    else {
        diff = 1;
    }

    // Update the values of nodes in segment tree
    updateValueUtil(tree, 0, n - 1, i, diff, 0);
}


// Return number of primes in range from index qs to qe
public static int queryPrimes(List<int> tree, int n, int qs, int qe) {
    return queryPrimesUtil(tree, 0, n - 1, qs, qe, 0);
}


public static List<int> findPrimes(int n) {
    List<int> primes = Enumerable.Repeat(1, n + 1).ToList();
    primes[0] = 0;
    primes[1] = 0;
    for (int i = 2; i * i <= n; i++) {
        if (primes[i] == 1) {
            for (int j = i * i; j <= n; j += i) {
                primes[j] = 0;
            }
        }
    }
    return primes;
}


public static List<int> solveQueries(List<int> arr, 
        List<List<int>> queries) {
    int n = arr.Count;

    // to store the result of query of type 1
    List<int> res = new List<int>();

    List<int> primes = findPrimes(1000000);

    // construct segment tree from given array
    List<int> tree = constructST(arr, n, primes);

    // process all the queries
    foreach (List<int> query in queries) {

        // to find the number of primes in the range [L, R]
        if (query[0] == 1) {
            int l = query[1];
            int r = query[2];
            int cnt = queryPrimes(tree, n, l, r);
            res.Add(cnt);
        }

        // else update the value of arr[i]
        else if (query[0] == 2) {
            int i = query[1];
            int x = query[2];
            updateValue(arr, tree, n, i, x, primes);
        }
    }
    return res;
}


public static void Main(string[] args) {
    List<int> arr = new List<int> {1, 2, 3, 5, 7, 9};
    List<List<int>> queries = new List<List<int>> {
        new List<int> {1, 0, 4}, new List<int> {2, 3, 6}, new List<int> {1, 0, 4}
    };
    List<int> res = solveQueries(arr, queries);
    foreach (int i in res) {
        Console.Write(i + " ");
    }
}

}

JavaScript

// A utility function to get the // middle index from corner indexes. function getMid(s, e) { return s + (e - s) / 2; }

// A recursive function that constructs Segment Tree // for array[ss..se]. function constructSTUtil(arr, ss, se, tree, si, primes) {

// If there is one element in array, check if it
// is prime then store 1 in the segment tree else
// store 0 and return
if (ss === se) {

    // if arr[ss] is prime
    if (primes[arr[ss]] === 1) 
        tree[si] = 1;        
    else 
        tree[si] = 0;
    
    return tree[si];
}

// 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
const mid = getMid(ss, se);
tree[si] = constructSTUtil(arr, ss, mid, tree, si * 2 + 1, primes) + 
           constructSTUtil(arr, mid + 1, se, tree, si * 2 + 2, primes);
return tree[si];

}

//Function to construct segment tree from given array. function constructST(arr, n, primes) {

// Height of segment tree
const x = Math.ceil(Math.log2(n));

// Maximum size of segment tree
const max_size = 2 * Math.pow(2, x) - 1;

const tree = Array(max_size).fill(0);

// Fill the allocated memory tree
constructSTUtil(arr, 0, n - 1, tree, 0, primes);

// Return the constructed segment tree
return tree;

}

// A recursive function to get the number // of primes in a given range function queryPrimesUtil(tree, ss, se, qs, qe, index) {

// If segment of this node is a part of given range
// then return the number of primes in the segment
if (qs <= ss && qe >= se) 
    return tree[index];

// If segment of this node is outside the given range
if (se < qs || ss > qe) 
    return 0;

// If a part of this segment overlaps with the given range
const mid = getMid(ss, se);
return queryPrimesUtil(tree, ss, mid, qs, qe, 2 * index + 1) + 
       queryPrimesUtil(tree, mid + 1, se, qs, qe, 2 * index + 2);

}

// A recursive function to update the nodes // which have the given index in their range. function updateValueUtil(tree, ss, se, i, diff, si) {

// Base Case: If the input index lies
// outside the range of this segment
if (i < ss || i > se) 
    return;

// If the input index is in range of this node,
// update the value of the node and its children
tree[si] = tree[si] + diff;
if (se !== ss) {
    const mid = getMid(ss, se);
    updateValueUtil(tree, ss, mid, i, diff, 2 * si + 1);
    updateValueUtil(tree, mid + 1, se, i, diff, 2 * si + 2);
}

}

// The function to update a value in input array and segment tree. // It uses updateValueUtil() to update the value in segment tree function updateValue(arr, tree, n, i, new_val, primes) {

// Check for erroneous input index
if (i < 0 || i > n - 1) {
    console.log("Invalid Input");
    return;
}

const oldValue = arr[i];

// Update the value in array
arr[i] = new_val;

// Case 1: Old and new values both are primes
if (primes[oldValue] === 1 && primes[new_val] === 1) 
    return;

// Case 2: Old and new values both non primes
if (primes[oldValue] === 0 && primes[new_val] === 0) 
    return;

let diff;
// Case 3: Old value was prime, new value is non prime
if (primes[oldValue] === 1 && primes[new_val] === 0) {
    diff = -1;
}

// Case 4: Old value was non prime, new_val is prime
else {
    diff = 1;
}

// Update the values of nodes in segment tree
updateValueUtil(tree, 0, n - 1, i, diff, 0);

}

// Return number of primes in range from index qs to qe function queryPrimes(tree, n, qs, qe) { return queryPrimesUtil(tree, 0, n - 1, qs, qe, 0); }

function findPrimes(n) { const primes = Array(n + 1).fill(1); primes[0] = 0; primes[1] = 0; for (let i = 2; i * i <= n; i++) { if (primes[i] === 1) { for (let j = i * i; j <= n; j += i) { primes[j] = 0; } } } return primes; }

function solveQueries(arr, queries) { const n = arr.length;

// to store the result of query of type 1
const res = [];

const primes = findPrimes(1000000);

// construct segment tree from given array
const tree = constructST(arr, n, primes);

// process all the queries
for (const query of queries) {

    // to find the number of primes in the range [L, R]
    if (query[0] === 1) {
        const l = query[1];
        const r = query[2];
        const cnt = queryPrimes(tree, n, l, r);
        res.push(cnt);
    }

    // else update the value of arr[i]
    else if (query[0] === 2) {
        const i = query[1];
        const x = query[2];
        updateValue(arr, tree, n, i, x, primes);
    }
}
return res;

}

const arr = [1, 2, 3, 5, 7, 9]; const queries = [[1, 0, 4], [2, 3, 6], [1, 0, 4]]; const res = solveQueries(arr, queries); res.forEach(i => process.stdout.write(i + " "));

`

Related Topic: **Segment Tree