# Range and Update Sum Queries with Factorial

Given an array **arr[]** of **N** integers and number of queries **Q**. The task is to answer three types of queries.

**Update [l, r]**– for every**i**in range**[l, r]**increment**arr[i]**by**1**.**Update [l, val]**– change the value of**arr[l]**to**val**.**Query [l, r]**– calculate the sum of**arr[i]! % 10**for all^{9}**i**in range**[l, r]**where**arr[i]!**is the**factorial**of**arr[i]**.

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

**Examples:**

Input:Q = 6, arr[] = { 1, 2, 1, 4, 5 }

3 1 5

1 1 3

2 2 4

3 2 4

1 2 5

3 1 5

Output:

148

50

968

1^{st}query, the required sum is (1! + 2! + 1! + 4! + 5!) % 10^{9}= 148

2^{nd}query, the array becomes arr[] = { 2, 3, 2, 4, 5 }

3^{rd}query, array becomes arr[] = { 2, 4, 2, 4, 5 }

4^{th}query, the required sum is (4! + 2! + 4!) % 10^{9}= 50

5^{th}query, the array becomes arr[] = { 2, 5, 3, 5, 6 }

6^{th}query, the required sum is (2! + 5! + 3! + 5! + 6!) % 10^{9}= 968

**Naive Approach:** A simple solution is to run a loop from **l** to **r** and calculate sum of factorial of elements (pre-computed) in the given range for the **3 ^{rd}** query. For the

**2**query, to update a value, simply replace

^{nd}**arr[i]**with the given value i.e.

**arr[i] = val**. For the

**1**type query, increment the value of

^{st}**arr[i]**i.e.

**arr[i] = arr[i] + 1**.

**Efficient Approach:** It can be observed from careful analysis that **40!** is divisible by 10^{9}, that means factorial of every number greater than **40** will be divisible by **10 ^{9}**. Hence, that adds zero to our answer for the

**3**query. The idea is to reduce the time complexity for each query and update operation to

^{rd}**O(logN)**. Use Binary Indexed Trees (BIT) or Segment Trees. Construct a

**BIT[]**array and have two functions for query and update operation.

- Now, for each update operation of the
**1**, the key observation is that the number in given range can at max be updated to^{st}type**40**, since after that it won’t matter as it will add zero to our final answer. We will use a set to store the index of only those numbers which are lesser than 10 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]**becomes greater than or equal to**40**after incrementing by**1**, remove it from the set as it will not affect our answer of sum query even after any next update query. - For the update operation of the
**2**, call the update function with the given value. Also, the given value is^{nd}type**< 40**, insert the index of the element to be replaced with into the set and if the given value is**≥ 40**, remove it from the set since it will have no importance in sum query. - For the sum query of the
**3**, simply do^{rd}type**query(r) – query(l – 1)**.

Below is the implementation of the above approach:

`// CPP program to calculate sum of ` `// factorials in an interval and update ` `// with two types of operations ` `#include <bits/stdc++.h> ` `using` `namespace` `std; ` ` ` `// Modulus ` `const` `int` `MOD = 1e9; ` ` ` `// Maximum size of input array ` `const` `int` `MAX = 100; ` ` ` `// Size for factorial array ` `const` `int` `SZ = 40; ` ` ` `int` `BIT[MAX + 1], fact[SZ + 1]; ` ` ` `// structure for queries with members type, ` `// leftIndex, rightIndex of the query ` `struct` `queries { ` ` ` `int` `type, l, r; ` `}; ` ` ` `// 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) ` `{ ` ` ` `// Precomputing factorials ` ` ` `fact[0] = 1; ` ` ` `for` `(` `int` `i = 1; i < 41; i++) ` ` ` `fact[i] = (fact[i - 1] * i) % MOD; ` ` ` ` ` `// Declaring a Set ` ` ` `set<` `int` `> s; ` ` ` `for` `(` `int` `i = 1; i < n; i++) { ` ` ` ` ` `// inserting indexes of those ` ` ` `// numbers which are lesser ` ` ` `// than 40 ` ` ` `if` `(arr[i] < 40) { ` ` ` `s.insert(i); ` ` ` `update(i, fact[arr[i]], n); ` ` ` `} ` ` ` `else` ` ` `update(i, 0, n); ` ` ` `} ` ` ` ` ` `for` `(` `int` `i = 0; i < q; i++) { ` ` ` ` ` `// update query of the 1st type ` ` ` `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; ` ` ` `int` `val = arr[*it] + 1; ` ` ` ` ` `// update the value of arr[i] to ` ` ` `// its new value ` ` ` `update(*it, fact[val] - fact[arr[*it]], n); ` ` ` ` ` `arr[*it]++; ` ` ` ` ` `// if updated value becomes greater ` ` ` `// than or equal to 40 remove it from ` ` ` `// the set ` ` ` `if` `(arr[*it] >= 40) ` ` ` `s.erase(*it); ` ` ` ` ` `// increment the index ` ` ` `que[i].l++; ` ` ` `} ` ` ` `} ` ` ` ` ` `// update query of the 2nd type ` ` ` `else` `if` `(que[i].type == 2) { ` ` ` `int` `idx = que[i].l; ` ` ` `int` `val = que[i].r; ` ` ` ` ` `// update the value to its new value ` ` ` `update(idx, fact[val] - fact[arr[idx]], n); ` ` ` ` ` `arr[idx] = val; ` ` ` ` ` `// If the value is less than 40, insert ` ` ` `// it into set, otherwise remove it ` ` ` `if` `(val < 40) ` ` ` `s.insert(idx); ` ` ` `else` ` ` `s.erase(idx); ` ` ` `} ` ` ` ` ` `// sum query of the 3rd type ` ` ` `else` ` ` `cout << (sum(que[i].r) - sum(que[i].l - 1)) ` ` ` `<< endl; ` ` ` `} ` `} ` ` ` `// Driver Code to test above functions ` `int` `main() ` `{ ` ` ` `int` `q = 6; ` ` ` ` ` `// input array using 1-based indexing ` ` ` `int` `arr[] = { 0, 1, 2, 1, 4, 5 }; ` ` ` `int` `n = ` `sizeof` `(arr) / ` `sizeof` `(arr[0]); ` ` ` ` ` `// declaring array of structure of type queries ` ` ` `queries que[q + 1]; ` ` ` ` ` `que[0].type = 3, que[0].l = 1, que[0].r = 5; ` ` ` `que[1].type = 1, que[1].l = 1, que[1].r = 3; ` ` ` `que[2].type = 2, que[2].l = 2, que[2].r = 4; ` ` ` `que[3].type = 3, que[3].l = 2, que[3].r = 4; ` ` ` `que[4].type = 1, que[4].l = 2, que[4].r = 5; ` ` ` `que[5].type = 3, que[5].l = 1, que[5].r = 5; ` ` ` ` ` `// answer the Queries ` ` ` `answerQueries(arr, que, n, q); ` ` ` `return` `0; ` `} ` |

*chevron_right*

*filter_none*

**Output:**

148 50 968

## Recommended Posts:

- Binary Indexed Tree : Range Update and Range Queries
- Queries to update a given index and find gcd in range
- Range Sum Queries and Update with Square Root
- Range and Update Query for Chessboard Pieces
- Difference Array | Range update query in O(1)
- Segment Tree | Set 2 (Range Maximum Query with Node Update)
- Iterative Segment Tree (Range Maximum Query with Node Update)
- Count factorial numbers in a given range
- Range LCM Queries
- Min-Max Range Queries in Array
- Subset Sum Queries in a Range using Bitset
- Sudo Placement | Range Queries
- Queries for number of array elements in a range with Kth Bit Set
- Queries to check whether a given digit is present in the given Range
- Array range queries for elements with frequency same as value

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.