# C++ Range Sum Queries and Update with Square Root

Given an array and several queries. Also, there are two types of query, i.e., update[ L, R ] means update elements from L to R with their square roots, and query[ L, R ] means to calculate the sum of elements from L to R.We are assuming a 1-based indexed array, for example

Input: nums[ ] = { 0, 9, 4, 1, 5, 2, 3 }, Query[ ] = { {1, 1, 3}, {2, 1, 2}, {1, 2, 5}, { 1, 4, 5}}
Output: 14
10
7
1st element of 1st query is 1 means we need to calculate range sum from 1 to 3 i.e 9 + 4 + 1 = 14

1st element of 2nd query is 2 means we need to update range element from 1 to 2 with their square roots now new arr[] array is { 3, 2, 1, 5, 2, 3 }

1st element of 3rd query is 1 means we need to calculate range sum from 2 to 5 i.e 2 + 1 + 5 + 2 = 10

1st element of the 4th query is 1 means we need to calculate the range sum from 4 to 5 i.e 5 + 2 = 7

Input: nums[] = { 0, 3, 2, 4, 16, 2 }, Query[ ] = {{1, 1, 3}, {2, 2, 5}}
Output: 9

## Approach to Find the Solution

### Simple Approach

We can use a loop till queries end and return the sum of range for sum query and update the array for the update query. But time complexity of this program will be O(q * n). Let’s look for an efficient approach.

### Efficient Approach

Program could be efficient if we decrease the number of operations or number of iterations. We can use Binary Indexed Trees, in which we create an array and use two functions for update and sum query. For the update query, if the element is 1, there is no need to update it as its square root will be one only. Now we can use a set to store the index of greater than one and use binary search for finding Lth index and increment it till every range element is updated. Then check if the updated value becomes one, then remove that index from the set because it will always be 1 for any update queries.

For the sum query, we can do query(R) - query(L-1).

## Example

C++ Code for the Above Approach

#include <bits/stdc++.h>
using namespace std;
// Maximum size input array can be
const int m = 200;
// Creating Binary Indexed tree.
int binary_indexed[m + 1];
// for update query
void update_q(int a, int x, int n){
while(a <= n) {
binary_indexed[a] += x;
a += a & -a;
}
}
// Function to calculate sum range.
int sum_q(int a){
int s = 0;
while(a > 0) {
s += binary_indexed[a];
a -= a & -a;
}
return s;
}
int main(){
int no_query = 4;
int nums[] = {   0, 9, 4, 1, 5, 2, 3 };
int n = sizeof(nums) / sizeof(nums[0]);
// 2-D array for queries.
int q[no_query + 1][3];
q[0][0] = 1, q[0][1] = 1, q[0][2] = 3;
q[1][0] = 2, q[1][1] = 1, q[1][2] = 2;
q[2][0] = 1, q[2][1] = 2, q[2][2] = 5;
q[3][0] = 1, q[3][1] = 4, q[3][2] = 5;
set<int> s;
for (int i = 1; i < n; i++) {
// Inserting indexes in the set of elements that are greater than 1.
if (nums[i] > 1)
s.insert(i);
update_q(i, nums[i], n);
}
for (int i = 0; i < no_query; i++) {
// Checking 0th index for update query or sum query.
if (q[i][0] == 2) {
while (true) {
// Finding the left index using binary search
auto it = s.lower_bound(q[i][1]);
// checking whether it reaches right index.
if (it == s.end() || *it > q[i][2])
break;
q[i][1] = *it;
// updating array element to their square roots.
update_q(*it, (int)sqrt(nums[*it]) - nums[*it], n);
nums[*it] = (int)sqrt(nums[*it]);
//checking if updated value is 1 the removing it from set
if (nums[*it] == 1)
s.erase(*it);
q[i][1]++;
}
} else {
cout <<"query" << i+1 <<": " << (sum_q(q[i][2]) - sum_q(q[i][1] - 1)) << endl;
}
}
return 0;
}

query1: 14
query3: 10
query4: 7

## Conclusion

In this tutorial, we discussed the range sum query and range update query for the array. We discussed a simple approach to solve this problem and an efficient approach by using Binary Indexed Tree. We also discussed the C++ program for this problem which we can do with programming languages like C, Java, Python, etc. We hope you find this tutorial helpful.