Given an array A of N integers. You have to answer two types of queries :

1. Update [l, r] – for every i in range from l to r update A_{i} with D(A_{i}), where D(A_{i}) represents the number of divisors of A_{i}

2. Query [l, r] – calculate the sum of all numbers ranging between l and r in array A.

Input is given as two integers N and Q, representing number of integers in array and number of queries respectively. Next line contains an array of n integers followed by Q queries where ith query is represented as type_{i}, l_{i}, r_{i}.

**Prerequisite : ** Binary Indexed Trees | Segment Trees

Examples :

Input : 7 4 6 4 1 10 3 2 4 2 1 7 2 4 5 1 3 5 2 4 4 Output : 30 13 4

**Explanation :** First query is to calculate the sum of numbers from A_{1} to A_{7} which is 6 + 4

+ 1 + 10 + 3 + 2 + 4 = 30. Similarly, second query results into 13. For third query,

which is update operation, hence A_{3} will remain 1, A_{4} will become 4 and A_{5} will become 2.

Fourth query will result into A_{4} = 4.

**Naive Approach : **

A simple solution is to run a loop from l to r and calculate sum of elements in given range. To update a value, precompute the values of number of divisors of every number and simply do arr[i] = divisors[arr[i]].

**Efficient Approach : **

The idea is to reduce the time complexity for each query and update operation to O(logN). Use Binary Indexed Trees (BIT) or Segment Trees. Construct a BIT[] array and have two functions for query and update operation and precompute the number of divisors for each number. Now, for each update operation the key observation is that the numbers ‘1’ and ‘2’ will have ‘1’ and ‘2’ as their number of divisors respectively, so if it exists in the range of update query, they don’t need to be updated. We will use a set to store the index of only those numbers which are greater than 2 and use binary search to find the l index of the update query and increment the l index until every element is updated in range of that update query. If the arr[i] has only 2 divisors then after updating it, remove it from the set as it will always be 2 even after any next update query. For sum query operation, simply do query(r) – query(l – 1).

[sourcecode language=”CPP”]

// CPP program to calculate sum

// in an interval and update with

// number of divisors

#include <bits/stdc++.h>

using namespace std;

int divisors[100], BIT[100];

// structure for queries with members type,

// leftIndex, rightIndex of the query

struct queries

{

int type, l, r;

};

// function to calculate the number

// of divisors of each number

void calcDivisors()

{

for (int i = 1; i < 100; i++) {

for (int j = i; j < 100; j += i) {

divisors[j]++;

}

}

}

// function for updating the value

void update(int x, int val, int n)

{

for (x; x <= n; x += x&-x) {

BIT[x] += val;

}

}

// function for calculating the required

// sum between two indexes

int sum(int x)

{

int s = 0;

for (x; x > 0; x -= x&-x) {

s += BIT[x];

}

return s;

}

// function to return answer to queries

void answerQueries(int arr[], queries que[], int n, int q)

{

// Declaring a Set

set<int> s;

for (int i = 1; i < n; i++) {

// inserting indexes of those numbers

// which are greater than 2

if(arr[i] > 2) s.insert(i);

update(i, arr[i], n);

}

for (int i = 0; i < q; i++) {

// update query

if (que[i].type == 1) {

while (true) {

// find the left index of query in

// the set using binary search

auto it = s.lower_bound(que[i].l);

// if it crosses the right index of

// query or end of set, then break

if(it == s.end() || *it > que[i].r) break;

que[i].l = *it;

// update the value of arr[i] to

// its number of divisors

update(*it, divisors[arr[*it]] – arr[*it], n);

arr[*it] = divisors[arr[*it]];

// if updated value becomes less than or

// equal to 2 remove it from the set

if(arr[*it] <= 2) s.erase(*it);

// increment the index

que[i].l++;

}

}

// sum query

else {

cout << (sum(que[i].r) – sum(que[i].l – 1)) << endl;

}

}

}

// Driver Code

int main()

{

// precompute the number of divisors for each number

calcDivisors();

int q = 4;

// input array

int arr[] = {0, 6, 4, 1, 10, 3, 2, 4};

int n = sizeof(arr) / sizeof(arr[0]);

// declaring array of structure of type queries

queries que[q + 1];

que[0].type = 2, que[0].l = 1, que[0].r = 7;

que[1].type = 2, que[1].l = 4, que[1].r = 5;

que[2].type = 1, que[2].l = 3, que[2].r = 5;

que[3].type = 2, que[3].l = 4, que[3].r = 4;

// answer the Queries

answerQueries(arr, que, n, q);

return 0;

}

[/sourcecode]

**Output:**

30 13 4

**Time Complexity for answering Q queries will be O(Q * log(N)).**

## Recommended Posts:

- Querying maximum number of divisors that a number in a given range has
- Number of divisors of product of N numbers
- Range and Update Sum Queries with Factorial
- Difference Array | Range update query in O(1)
- Range Sum Queries and Update with Square Root
- Range and Update Query for Chessboard Pieces
- MongoDB Python | Insert and Update Data
- Segment Tree | Set 2 (Range Maximum Query with Node Update)
- Iterative Segment Tree (Range Maximum Query with Node Update)
- Binary Indexed Tree : Range Update and Range Queries
- Count Divisors of n in O(n^1/3)
- Divide the two given numbers by their common divisors
- Find largest sum of digits in all divisors of n
- Puzzle | Number of Sheets to be turned so that Prime Number has a Vowel on the other side
- Number of elements less than or equal to a given number in a given subarray | Set 2 (Including Updates)

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.