|
| 1 | +# LOJ 1369 - Answering Queries |
| 2 | + |
| 3 | +First let's understand what the given code is doing. |
| 4 | +There will be two types of queries, one is calculating the sum and the other |
| 5 | +one is to change the value of an element of the given array `A[]`. |
| 6 | +If you calculate the sum in the way the given code does, the complexity of |
| 7 | +the code will be O(t * q * n * n), which will not fit in the Time limit. |
| 8 | +So, we need to do the same thing what the given code does but in an efficient |
| 9 | +way. But what that way could be? Let's see! |
| 10 | + |
| 11 | +We can use _contribution technique_ to solve this problem. Firstly, we will |
| 12 | +determine how much contribution an element of the array does to the `sum`. |
| 13 | + |
| 14 | +For example, let's take an array of four elements {1, 4, -2, 8}. |
| 15 | +The `sum` will be the summation of (1-4) + (1-(-2)) + (1-8), (4-(-2)) + (4-8) and (-2-8). |
| 16 | +Here first element is summed for 3 times and subtracted for 0 times, |
| 17 | +so the contribution of 1 to the `sum` is 3 - 0 = 3. |
| 18 | +Again second element is summed for 2 times and subtracted for 1 times, |
| 19 | +so the contribution of 4 to the `sum` is 2 - 1 = 1. |
| 20 | +In the same way, the contributions of the third element -2 |
| 21 | +and fourth element 8 to the `sum` are -1 and -2 respectively. |
| 22 | + |
| 23 | +So, in this way we will calculate the contribution of each element of the |
| 24 | +array to the `sum` and store it to an array named `contribution[n]`. |
| 25 | +_How can we do that?_ |
| 26 | + |
| 27 | +Observe the pattern: each element is summed for the exact same number of |
| 28 | +elements it has after it and that number will be `(n - index - 1)`. |
| 29 | +In the same way, each element is subtracted for the exact same number of |
| 30 | +elements it has before it and that number is the index of that element `index`. |
| 31 | +So we can calculate the contribution of each element in this way: |
| 32 | +``` |
| 33 | +contribution[index] = (n - index - 1) - index; |
| 34 | +``` |
| 35 | + |
| 36 | +Now we can calculate the `sum` by going through every element of the array |
| 37 | +and add `A[index] * contribution[index]` to the sum. |
| 38 | +Even if the value of an element changes, the corresponding value in the |
| 39 | +`contribution` array of that element will still remain the same, because |
| 40 | +`contribution` array has nothing to do with elements' value rather it |
| 41 | +tells us how `sum` is calculated. |
| 42 | + |
| 43 | +So, when the query will be to change the value of an element, we will just |
| 44 | +recalculate the `sum` in the following manner in constant time, |
| 45 | +no need to loop over the whole array. |
| 46 | + |
| 47 | +``` |
| 48 | +sum -= arr[x] * contribution[x]; |
| 49 | +arr[x] = v; |
| 50 | +sum += arr[x] * contribution[x]; |
| 51 | +``` |
| 52 | + |
| 53 | +The time complexity of this approach will be O(t * (n + q)). _How?_ |
| 54 | + |
| 55 | +### C++ Code |
| 56 | + |
| 57 | +```cpp |
| 58 | + |
| 59 | +/* |
| 60 | + Author: Arup Debnath |
| 61 | + Date: 24 March, 2023 |
| 62 | +
|
| 63 | + Happy Coding!! |
| 64 | +*/ |
| 65 | + |
| 66 | +#include <bits/stdc++.h> |
| 67 | +#define N ((int)1e5 + 5) |
| 68 | + |
| 69 | +using namespace std; |
| 70 | + |
| 71 | +int A[N]; |
| 72 | +int contribution[N]; |
| 73 | + |
| 74 | +int main() |
| 75 | +{ |
| 76 | + ios_base::sync_with_stdio(false); |
| 77 | + cin.tie(NULL); |
| 78 | + |
| 79 | + int t; |
| 80 | + cin>>t; |
| 81 | + for(int i = 1; i <= t; i++) { |
| 82 | + int n, q; |
| 83 | + cin>>n>>q; |
| 84 | + |
| 85 | + long long sum = 0; |
| 86 | + |
| 87 | + for(int j = 0; j < n; j++) { |
| 88 | + cin>>A[j]; |
| 89 | + contribution[j] = (n-j-1) - j; |
| 90 | + sum += 1LL * A[j] * contribution[j]; |
| 91 | + // multiplying by 1LL is important because A[j] * contribution[j] |
| 92 | + // can be greater than INT_MAX (2^31 - 1) |
| 93 | + } |
| 94 | + |
| 95 | + cout << "Case " << i << ":\n"; |
| 96 | + while(q--) { |
| 97 | + int type; |
| 98 | + cin>>type; |
| 99 | + if(type == 0) { |
| 100 | + int idx, val; |
| 101 | + cin>>idx>>val; |
| 102 | + sum -= 1LL * A[idx] * contribution[idx]; |
| 103 | + A[idx] = val; |
| 104 | + sum += 1LL * A[idx] * contribution[idx]; |
| 105 | + } else { |
| 106 | + cout << sum << "\n"; |
| 107 | + } |
| 108 | + } |
| 109 | + } |
| 110 | +} |
| 111 | +``` |
0 commit comments