You can do this in O (qlog (n)), where q is the number of requests.
The idea is to use BIT (binary indexed trees)
// C++ program to demonstrate Range Update // and Range Queries using BIT #include <iostream> using namespace std; // Returns sum of arr[0..index]. This function assumes // that the array is preprocessed and partial sums of // array elements are stored in BITree[] int getSum(int BITree[], int index) { int sum = 0; // Initialize result // index in BITree[] is 1 more than the index in arr[] index = index + 1; // Traverse ancestors of BITree[index] while (index>0) { // Add current element of BITree to sum sum += BITree[index]; // Move index to parent node in getSum View index -= index & (-index); } return sum; } // Updates a node in Binary Index Tree (BITree) at given // index in BITree. The given value 'val' is added to // BITree[i] and all of its ancestors in tree. void updateBIT(int BITree[], int n, int index, int val) { // index in BITree[] is 1 more than the index in arr[] index = index + 1; // Traverse all ancestors and add 'val' while (index <= n) { // Add 'val' to current node of BI Tree BITree[index] += val; // Update index to that of parent in update View index += index & (-index); } } // Returns the sum of array from [0, x] int sum(int x, int BITTree1[], int BITTree2[]) { return (getSum(BITTree1, x) * x) - getSum(BITTree2, x); } void updateRange(int BITTree1[], int BITTree2[], int n, int val, int l, int r) { // Update Both the Binary Index Trees // As discussed in the article // Update BIT1 updateBIT(BITTree1,n,l,val); updateBIT(BITTree1,n,r+1,-val); // Update BIT2 updateBIT(BITTree2,n,l,val*(l-1)); updateBIT(BITTree2,n,r+1,-val*r); } int rangeSum(int l, int r, int BITTree1[], int BITTree2[]) { // Find sum from [0,r] then subtract sum // from [0,l-1] in order to find sum from // [l,r] return sum(r, BITTree1, BITTree2) - sum(l-1, BITTree1, BITTree2); } int *constructBITree(int n) { // Create and initialize BITree[] as 0 int *BITree = new int[n+1]; for (int i=1; i<=n; i++) BITree[i] = 0; return BITree; } // Driver Program to test above function int main() { int n = 5; // Construct two BIT int *BITTree1, *BITTree2; // BIT1 to get element at any index // in the array BITTree1 = constructBITree(n); // BIT 2 maintains the extra term // which needs to be subtracted BITTree2 = constructBITree(n); // Add 5 to all the elements from [0,4] int l = 0 , r = 4 , val = 5; updateRange(BITTree1,BITTree2,n,val,l,r); // Add 2 to all the elements from [2,4] l = 2 , r = 4 , val = 10; updateRange(BITTree1,BITTree2,n,val,l,r); // Find sum of all the elements from // [1,4] l = 1 , r = 4; cout << "Sum of elements from [" << l << "," << r << "] is "; cout << rangeSum(l,r,BITTree1,BITTree2) << "\n"; return 0; }
An effective solution is to ensure that both requests can be executed in O (Log n). We get the amount of the amount using prefix amounts. How to make sure that the update is done so that the amount of the prefix can be completed quickly? Consider the situation when the prefix sum [0, k] (where 0 <= k <n) is necessary after updating the range in the range [l, r]. Three cases arise, since k can be in three regions.
Case 1: 0 <k <L The update request does not affect the amount request.
Case 2: l <= k <= r Consider an example:
Add 2 to the range [2, 4], the resulting array will be: 0 0 2 2 2 If k = 3 The sum of [0, k] = 4 How to get this result? Just add val from the lth index to the kth index. The amount increases by "val * (k) - val * (l-1)" after the update request.
Case 3: k> r For this case, we need to add "val" from the lth index to the rth index. The amount increases by "valr - val (l-1)" due to an update request.
Observations: Case 1: simple, as the amount will remain the same as before the update.
Case 2: the amount was increased by valk-val (l-1). We can find "val", it looks like searching for the ith element in updating a range and an article with query points. Thus, we support one BIT for Range and Point Queries updates, this BIT will be useful when searching for a value in the kth index. Now val * k is calculated, how to handle the additional term val * (l-1)? To cope with this extra deadline, we support another BIT (BIT2). Update val * (l-1) at the l-th index, so when getSum is executed on BIT2, the result will be obtained as val * (l-1).
Case 3: the sum in case 3 was increased by "val * r - val (l-1)", the value of this member can be obtained using BIT2. Instead of adding, we subtract "val (l-1) - valr", since we can get this value from BIT2 by adding val (l-1), as it was in case 2, and subtract val * r in each update operation.
Update Query Update(BITree1, l, val) Update(BITree1, r+1, -val) UpdateBIT2(BITree2, l, val*(l-1)) UpdateBIT2(BITree2, r+1, -val*r) Range Sum getSum(BITTree1, k) *k) - getSum(BITTree2, k)
Source: geeksforgeeks.org