# 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
- 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 to check whether a given digit is present in the given Range
- Array range queries for elements with frequency same as value
- Queries for number of array elements in a range with Kth Bit Set
- Range queries to count 1s in a subarray after flip operations

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.