We are given an array A with N elements and also N ranges, each of the form [L, R]. Call the value of a range the sum of all the elements in A from index L to index R, inclusive.
Example : Let Array A = [2 5 7 9 8] and a range given is [2,4] then value of this range is 5+7+9=21
Now we are given Q queries each query of one of the 2 types:
1. 0 X Y : It means change Xth element of array to Y.
2. 1 A B : It means we need to report the sum of values of ranges from A to B.
Example : Let array A = [2 3 7 8 6 5] and let we have 3 ranges :
R1: [1,3] Then value corresponding to this range is 2+3+7=12
R2: [4,5] Then value corresponding to this range is 8+6=14
R3: [3,6] Then value corresponding to this range is 7+8+6+5=26
Now let we have 3 queries:
Q1: 1 1 2
Then here answer is value of Range1 + value of Range2 = 12+14=26
Q2: 0 2 5
It means Change 2nd element to 5 from 3.It will change the result of Range 1.
Now value of Range1 becomes 2+5+7=14
Q3: 1 1 2
Then here answer is value of Range1 + value of Range2 = 14+14=28
How to do it if we have 10^5 Queries and N is also upto 10^5. How to report to Queries2 in an efficient way ?
My Approach : The first query can be handled easily. I can build a segment tree from the array. I can use it to calculate the sum of an interval in the first array (an element in the second array). But how can i handle the second query in O(log n)? In the worst case, the element I update will be in all the intervals in the second array.
I need a O(Qlog N) or O(Q(logN)^2) solution.
Obviously we cant have a O(N) for each query.So please help to get efficient way
My Current Code :
#include<bits/stdc++.h>
using namespace std;
long long arr[100002],i,n,Li[100002],Ri[100002],q,j;
long long queries[100002][2],query_val[100002],F[100002],temp;
long long ans[100002];
int main()
{
scanf("%lld",&n);
for(i=1;i<=n;i++)
scanf("%lld",&arr[i]);
for(i=1;i<=n;i++)
{
scanf("%lld%lld",&Li[i],&Ri[i]);
}
for(i=1;i<=n;i++)
{
F[n] = 0;
ans[i] = 0;
}
scanf("%lld",&q);
for(i=1;i<=q;i++)
{
scanf("%lld",&query_val[i]);
scanf("%lld%lld",&queries[i][0],&queries[i][1]);
}
for(i=1;i<=n;i++)
{
for(j=Li[i];j<=Ri[i];j++)
{
F[i] = F[i] + arr[j];
}
}
long long diff;
long long ans_count = 0,k=1;
for(i=1;i<=q;i++)
{
if(query_val[i] == 1)
{
temp = arr[queries[i][0]];
arr[queries[i][0]] = queries[i][1];
diff = arr[queries[i][0]] - temp;
for(j=1;j<=n;j++)
{
if(queries[i][0]>=Li[j] && queries[i][0]<=Ri[j])
F[j] = F[j] + diff;
++k;
}
}
else if(query_val[i] == 2)
{
++ans_count;
for(j=queries[i][0];j<=queries[i][1];j++)
ans[ans_count] = ans[ans_count] + F[j];
}
}
for(i=1;i<=ans_count;i++)
{
printf("%lld\n",ans[i]);
}
return 0;
}
Though the code is correct but for larger test cases it take huge time.Please help
You could use Segment Tree. http://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/
Basic idea is to extend your array of elements into a binary tree. Every node of that tree holds information about sum of the elements of its children. And you can easily know which range is some node covering by applying this trick:
Root is holding information of range
[1,N]
. Left child of the root is holding information about range[1, int(N/2)]
. Right child of the root is holding information about range[int(N/2)+1, N]
.In general if node 'A' is holding information about range
[l, r]
. Then left child holds information about range[l, int((l+r)/2)]
and right child is holding information about range[int((l+r)/2)+1, r]
.There is also a good trick to represent binary tree in array. Lets say that you hold your tree in array 'tree' (as I am doing I my code). Then root of that tree will be in
tree[1]
. Left child of the root is going to betree[2]
and right child of tree root is going to betree[3]
.In general if you are on the node
n
then its left child is2*n
and right child is2*n + 1
.That is why I am calling my
query
andupdate
function with (1, 0, N - 1). I start with the root node1
. And range that I am covering with that node i [0, N-1]. And I am always trying to find first node what fits in the range that I need to calculate the sum of.That's a start. Try googling more about Segment Trees. When you start exploring you will see that there is a couple of ways you can represent your tree.
Good luck. :)