Segment Tree and Lazy Propagation - HackerEarth

Download as pdf or txt
Download as pdf or txt
You are on page 1of 23

Signup and get free access to 100+ Tutorials and Practice Problems Start Now

 Notes

 Segment Tree and Lazy Propagation


214 Segment-tree Lazy-propagation CodeMonk Code Monk

There are many problems in which you need to query on intervals or segments of a collection
of items. For example, finding the sum of all the elements in an array from index left to right,
or finding the minimum of all the elements in an array from index left to right. These
problems can be easily solved with one of the most powerful data structures, Segment Tree (
in-short Segtree ).

What is Segment Tree ?


Segment tree or segtree is a basically a binary tree used for storing the intervals or segments.
Each node in the segment tree represents an interval.
Consider an array A of size N and a corresponding segtree T:

1. The root of T will represent the whole array A[0:N-1].


2. Each leaf in the segtree T will represent a single element A[i] such that 0 <= i < N.
3. The internal nodes in the segtree tree T represent union of elementary intervals A[i:j]
where 0 <= i < j < N.

The root of the segtree will represent the whole array A[0:N-1]. Then we will break the interval
or segment into half and the two children of the root will represent the A[0:(N-1) / 2] and A[(N-
1) / 2 + 1:(N-1)]. So in each step we will divide the interval into half and the two children will
represent the two halves. So the height of the segment tree will be log2N. There are N leaves
representing the N elements of the array. The number of internal nodes is N-1. So total
number of nodes are 2*N - 1.

Once we have built a segtree we cannot change its structure i.e., its structure is static. We can
update the values of nodes but we cannot change its structure. Segment tree is recursive in
nature. Because of its recursive nature, Segment tree is very easy to implement. Segment tree
provides two operations:

1. Update: In this operation we can update an element in the Array and reflect the
corresponding change in the Segment tree.
2. Query: In this operation we can query on an interval or segment and return the answer
to the problem on that particular interval.

Implementation: ?
Since a segtree is a binary tree, we can use a simple linear array to represent the segment
tree. In almost any segtree problem we need think about what we need to store in the
segment tree?.
For example, if we want to find the sum of all the elements in an array from index left to right,
then at each node (except leaf nodes) we will store the sum of its children nodes. If we want to
find the minimum of all the elements in an array from index left to right, then at each node
(except leaf nodes) we will store the minimum of its children nodes.

Once we know what we need to store in the segment tree we can build the tree using
recursion ( bottom-up approach ). We will start with the leaves and go up to the root and
update the corresponding changes in the nodes that are in the path from leaves to root.
Leaves represent a single element. In each step we will merge two children to form an internal
node. Each internal node will represent a union of its children’s intervals. Merging may be
different for different problems. So, recursion will end up at root which will represent the
whole array.

For update, we simply have to search the leaf that contains the element to update. This can be
done by going to either on the left child or the right child depending on the interval which
contains the element. Once we found the leaf, we will update it and again use the bottom-up
approach to update the corresponding change in the path from leaf to root.

To make a query on the segment tree we will be given a range from l to r. We will recurse on
the tree starting from the root and check if the interval represented by the node is completely
in the range from l to r. If the interval represented by a node is completely in the range from l
to r, we will return that node’s value. The segtree of array A of size 7 will look like :

?
?
All this we will get clear by taking an example. You can given an array A of size N and some
queries. There are two types of queries:

1. Update: add a value of an element to val in the array A at a particular position idx.
2. Query: return the value of A[l] + A[l+1] + A[l+2] + ….. + A[r-1] + A[r] such that 0 <= l <= r
<N

Naive Algorithm:
This is the most basic approach. For query simple run a loop from l to r and calculate the sum
of all the elements. So query will take O(N). A[idx] += val will update the value of the element.
Update will take O(1). This algorithm is good if the number of update operations are very large
and very few query operations. ?
Another Naive Algorithm:
In this approach we will preprocess and store the cumulative sum of the elements of the array
in an array sum. For each query simply return (sum[r] - sum[l-1]). Now query operation will
take O(1). But to update, we need to run a loop and change the value of all the sum[i] such
that l <= i <= r. So update operation will take O(N). This algorithm is good if the number of
query operations are very large and very few update operations.

Using Segment Tree:


Let us see how to use segment tree and what we will store in the segment tree in this
problem. As we know that each node of the segtree will represent an interval or segment. In
this problem we need to find the sum of all the elements in the given range. So in each node
we will store the sum of all the elements of the interval represented by the node. How do we
do that? We will build a segment tree using recursion ( bottom-up approach ) as explained
above. Each leaf will have a single element. All the internal nodes will have the sum of both of
its children.

void build(int node, int start, int end)


{
if(start == end)
{
// Leaf node will have a single element
tree[node] = A[start];
}
else
{
int mid = (start + end) / 2;
// Recurse on the left child
build(2*node, start, mid);
// Recurse on the right child
build(2*node+1, mid+1, end);
// Internal node will have the sum of both of its children
tree[node] = tree[2*node] + tree[2*node+1];
}
}

In the above code we will start from the root and recurse on the left and the right child until
we reach the leaves. From the leaves we will go back to the root and update all the nodes in
the path. node represent the current node we are processing. Since segment tree is a binary
tree. 2*node will represent the left node and 2*node + 1 represent the right node. start and
end represents the interval represented by the node. Complexity of build() is O(N).

?
To update an element we need to look at the interval in which the element is and recurse
accordingly on the left or the right child.

void update(int node, int start, int end, int idx, int val)
{
if(start == end)
{
// Leaf node
A[idx] += val;
tree[node] += val;
}
else
{
int mid = (start + end) / 2;
if(start <= idx and idx <= mid)
{
// If idx is in the left child, recurse on the left child
update(2*node, start, mid, idx, val);
}
?
else
{
// if idx is in the right child, recurse on the right child
update(2*node+1, mid+1, end, idx, val);
}
// Internal node will have the sum of both of its children
tree[node] = tree[2*node] + tree[2*node+1];
}
}

Complexity of update will be O(logN).

To query on a given range, we need to check 3 conditions.

1. range represented by a node is completely inside the given range


2. range represented by a node is completely outside the given range
3. range represented by a node is partially inside and partially outside the given range

If the range represented by a node is completely outside the given range, we will simply return
0. If the range represented by a node is completely inside the given range, we will return the
value of the node which is the sum of all the elements in the range represented by the node.
And if the range represented by a node is partially inside and partially outside the given range,
we will return sum of the left child and the right child. Complexity of query will be O(logN).

int query(int node, int start, int end, int l, int r)


{
if(r < start or end < l)
{
// range represented by a node is completely outside the given range
return 0;
}
if(l <= start and end <= r)
{
// range represented by a node is completely inside the given range
return tree[node];
}
// range represented by a node is partially inside and partially outside
the given range
int mid = (start + end) / 2;
int p1 = query(2*node, start, mid, l, r);
int p2 = query(2*node+1, mid+1, end, l, r);
return (p1 + p2);
}
?
Updating an interval ( Lazy Propagation ):

Sometimes problems will ask you to update an interval from l to r, instead of a single element.
One solution is to update all the elements one by one. Complexity of this approach will be O(N)
per operation since where are N elements in the array and updating a single element will take
O(logN) time.

To avoid multiple call to update function, we can modify the update function to work on an
interval.

void updateRange(int node, int start, int end, int l, int r, int val)
{
4
// out of range

LIVE EVENTS
if (start > end or start > r or end < l)
return;

// Current node is a leaf node


if (start == end)
{
// Add the difference to current node
tree[node] += val;
return;
}

// If not a leaf node, recur for children.


int mid = (start + end) / 2;
updateRange(node*2, start, mid, l, r, val);
updateRange(node*2 + 1, mid + 1, end, l, r, val);

// Use the result of children calls to update this node


tree[node] = tree[node*2] + tree[node*2+1];
}

Let's be Lazy i.e., do work only when needed. How ? When we need to update an interval, we
will update a node and mark its child that it needs to be updated and update it when needed.
For this we need an array lazy[] of the same size as that of segment tree. Initially all the
elements of the lazy[] array will be 0 representing that there is no pending update. If there is
non-zero element lazy[k] then this element needs to update node k in the segment tree before
making any query operation.

To update an interval we will keep 3 things in mind.

1. If current segment tree node has any pending update, then first add that pending update ?
to current node.
2. If the interval represented by current node lies completely in the interval to update, then
update the current node and update the lazy[] array for children nodes.
3. If the interval represented by current node overlaps with the interval to update, then
update the nodes as the earlier update function

Since we have changed the update function to postpone the update operation, we will have to
change the query function also. The only change we need to make is to check if there is any
pending update operation on that node. If there is a pending update operation, first update the
node and then work same as the earlier query function.

void updateRange(int node, int start, int end, int l, int r, int val)
{
if(lazy[node] != 0)
{
// This node needs to be updated
tree[node] += (end - start + 1) * lazy[node]; // Update it
if(start != end)
{
lazy[node*2] += lazy[node]; // Mark child as
lazy
lazy[node*2+1] += lazy[node]; // Mark child as
lazy
}
lazy[node] = 0; // Reset it
}
if(start > end or start > r or end < l) // Current segment
is not within range [l, r]
return;
if(start >= l and end <= r)
{
// Segment is fully within range
tree[node] += (end - start + 1) * val;
if(start != end)
{
// Not leaf node
lazy[node*2] += val;
lazy[node*2+1] += val;
}
return;
}
int mid = (start + end) / 2;
updateRange(node*2, start, mid, l, r, val); // Updating left child ?
updateRange(node*2 + 1, mid + 1, end, l, r, val); // Updating right
child
tree[node] = tree[node*2] + tree[node*2+1]; // Updating root with
max value
}

int queryRange(int node, int start, int end, int l, int r)


{
if(start > end or start > r or end < l)
return 0; // Out of range
if(lazy[node] != 0)
{
// This node needs to be updated
tree[node] += (end - start + 1) * lazy[node]; // Update
it
if(start != end)
{
lazy[node*2] += lazy[node]; // Mark child as lazy
lazy[node*2+1] += lazy[node]; // Mark child as lazy
}
lazy[node] = 0; // Reset it
}
if(start >= l and end <= r) // Current segment is totally
within range [l, r]
return tree[node];
int mid = (start + end) / 2;
int p1 = queryRange(node*2, start, mid, l, r); // Query left
child
int p2 = queryRange(node*2 + 1, mid + 1, end, l, r); // Query right child
return (p1 + p2);
}

Practice Problems:

1. Help Ashu
2. Roy And Coin Boxes
3. Comrades-III

Solve Problems

Like 21 Tweet

?
COMMENTS (104)  SORT BY: Relevance 

Login/Signup to Comment

Utkarsh Kumar 3 years ago


What is exactly mean by (end - start + 1) in lazy propagation?
 5 votes  Reply  Message  Permalink

Sidhanta Choudhury 3 years ago


suppose there is update for arr[start] to arr[end] adding v so total added is (end-start+1)*v
.As in a segment tree a node (tree[node] )gives sum of array values it covers ,so we
updated tree node as tree[node]+=(end-start+1)*v ,later we will update left and right node
 14 votes  Reply  Message  Permalink

Utkarsh Kumar 3 years ago


understood. Thanks!
 0 votes  Reply  Message  Permalink

Rajeev Kumar 3 years ago


There is a little mistake in the line "So total number of nodes are 2*N - 1", since this is not true
in every case. To be sure, that your recursive call does not cross the size limit, you should
declare your segment tree array of size 4*N.
 7 votes  Reply  Message  Permalink

Gaurav Sen 3 years ago


I don't think so. The tree size is 1+2+4+...+N. This a geometric progression with sum =a*
(lastTerm*r-1)/(r-1). Here r=2 and a=N and lastTerm=N. So we have sum =2*N-1.
 3 votes  Reply  Message  Permalink

Jatin Khurana 3 years ago


In case when A size is 6. How 2*N-1 is full filling the parent child relationship. It is
going out of array when we take parent 6 and calculating it's child.
 1 vote  Reply  Message  Permalink

Gaurav Sen 3 years ago


No. The N you take in this case is the smallest power of 2 greater than A->size.
That is equal to 8 in your case. Total size of segment tree will be 16 then.
 2 votes  Reply  Message  Permalink

Jatin Khurana 3 years ago


yes... in worst case size of segment tree is O(4*N)...
 4 votes  Reply  Message  Permalink

Punit Bhatt  Edited 2 years ago


in updateRange why dont we first check whether the segment is in the given interval ( start>end
or start>r or end<l ). Only if this condition is not satisfied should the lazy[node]!=0 condition be
checked.
Initially i thought the order wouldnt matter. But my solution for a particular question in
Codechef was not getting accepted (WA) but when i reversed the order it got accepted
(lazy[node] condition first).
Can anyone tell me the significance of this order of conditions ?
 7 votes  Reply  Message  Permalink

Ankur Dhir 2 years ago


same question ?
if someone knows please help..!!
 1 vote  Reply  Message  Permalink

Prashank Mehta 2 years ago


You should change the order. Author has used the same order as you suggested for query
range.
 0 votes  Reply  Message  Permalink

Kaneki Ken 2 years ago

irrespective of the range, the update must be applied so that further updates happen over
the current update so as to get the results of the queries correctly. The interval should not
be considered as a factor, just apply the updates so further updates make sense. Correct
me @author Akash if I am wrong.
 0 votes  Reply  Message  Permalink

kallu420 2 years ago


The point is that even if that is done what you are suggesting there must not be any
effect as the intervals will be out of range for the node, and this just increases one
recursive function call and that doesn't seems to be good..!!
Have a look at my comment below
 0 votes  Reply  Message  Permalink

kallu420  Edited 2 years ago


Another cool example and SOME TROUBLE, HELP NEEDED and APPRECIATED :
https://www.hackerearth.com/code-monk-segment-tree-and-lazy-
propagation/algorithm/monk-and-otakuland-1/
the above problem is solvable using lazy propagation and that is what has been done here
:
http://ideone.com/FfagL8
but to get the above code accepted you need to activate the comment block in /* */, and
deactivate the
un-comment // game starts here and // game ends here in the updateRange and query
methods..
I am not able to understand this behavior....
 1 vote  Reply  Message  Permalink

SARTHAK MITTAL 2 years ago


I had the same doubt. But see, if suppose you check for range first, in case of partial
overlap you recurse to the left and right child. Now the value of "node" is changed. The
child in lazy[node] can be zero even when the parent was not. So now you need to check
the zero for parent at (i-1)/2. I think this complicates the code more than the existing one.
Think about it.
 0 votes  Reply  Message  Permalink

Shubham Singh a year ago


I also faced the same.My all test cases except the last one ,failed due to ignoring this order.
But it seems very clear now. Note the last 3 statements of updateRange :
updateRange(node*2, start, mid, l, r, val); // Updating left child
updateRange(node*2 + 1, mid + 1, end, l, r, val); // Updating right child
tree[node] = tree[node*2] + tree[node*2+1]; // Updating root with max value
Note that you are calling the updateRange for both the left and right subtrees. Now
suppose that left and right nodes are lazy but still any of these does not fall in the current
required range to be updated. Now just think if you ignore the updation of these nodes ,
(just because they do not lie in the current range), how can the last line : i.e.
tree[node] = tree[node*2] + tree[node*2+1];
will get executed correctly . This last line uses the fresh values of the left and right nodes ,
therefore, we must update the left and right nodes irrespective of the fact that it lies in
current required range or not.
Hope it helps! :) ?
 5 votes  Reply  Message  Permalink

Sushant Gupta a year ago


Thanks. It helped
 0 votes  Reply  Message  Permalink

Shubham Singh a year ago


Pleasure! :)
 0 votes  Reply  Message  Permalink

prateekbehera 2 years ago


In the query function shouldn't it be if(l >= start and end >= r) instead of if(l <= start and end <=
r) in the range represented by a node is completely inside the given range if statement
 1 vote  Reply  Message  Permalink

Deepayan Bardhan 2 years ago


No...because we have invoked the funtion initially with start=0 & end=n-1 .... And it gets
divided into 2 halves ! when the condition if(l <= start and end <= r) gets satisfied , there's
another half working simultaneously so that thing will be taken care of !
 1 vote  Reply  Message  Permalink

Manohar Reddy Poreddy  Edited 2 years ago


Good question, my initial reaction was the same as you felt, then I worked out an example,
[L:R] being partly left side, and partly right side of root node, then it was more clear. Also
[L:R] being only on left or right side is also good simple example.
In simple, L & R are fixed, start and end are changing, getting smaller, at some time they
will be equal or less interval than L & R interval, which is what is (l <= start and end <= r).
Hope that helped.
 0 votes  Reply  Message  Permalink

Deepayan Bardhan 2 years ago


In updateRange funtion (before lazy propagation) why aren't we incrementing the the value of
a[start]+=val ??
 1 vote  Reply  Message  Permalink

Akash Sharma  Author 2 years ago


We can update it if we will use it. But in most case we don't need it as we have already
stored its information into the segtree and using segtree to answer the queries.
 1 vote  Reply  Message  Permalink

Deepayan Bardhan 2 years ago


Then why is that done for only a index update ??
 0 votes  Reply  Message  Permalink

Akash Sharma 2 years ago


It wont affect the answer unless you are using the array itself.
 0 votes  Reply  Permalink

Jayant Jain 8 months ago


yes bro you dont need add just replace it with a[start]=val;
tree[node]=val;
publisher has not properly explained it val he has used as difference between new value
and current value :)
 0 votes  Reply  Message  Permalink

Saurabh Suman 3 years ago ?


Shouldn't the time complexity for build be O(n). Value of every node is calculated only once.
 1 vote  Reply  Message  Permalink

Anubhav Gupta 3 years ago


I agree. Recurrence for build is: T(n) = 2T(n/2) + O(1) = O(n)
So, time complexity of build should be O(n).
 0 votes  Reply  Message  Permalink

Okeke Ugochukwu 3 years ago


I don't think so. It should be O(lgn). Note that the recurrence relation you wrote is the
same as that of binary search.
If a merge step is O(1) and you are at each iteration doing n/2 subproblems, then the
height of the abstract binary tree is lgn. And since we are not spending time to do
merging then everything is still lgn.
 0 votes  Reply  Message  Permalink

Anubhav Gupta 3 years ago


Hi Okeke,
recurrence for binary search is T(n) = T(n/2) + O(1)
but here it is T(n) = 2T(n/2) + O(1)
In binary search, we make only one recursive call on array of half the size, but
here we are making two calls on arrays of half the sizes. So, according to Master's
theorem it should be O(n).
 0 votes  Reply  Message  Permalink

Okeke Ugochukwu 3 years ago


Agreed!!! My bad.
 0 votes  Reply  Message  Permalink

Akash Sharma  Author 3 years ago


Thanks for pointing it out. Fixed :)
 0 votes  Reply  Message  Permalink

Murat Kurnaz 2 years ago


Is it really needed to write start > end in if statement. Isn't that impossible ?
 0 votes  Reply  Message  Permalink

Shubham Marathia 2 years ago


yes it is needed in order to break your recursion when it low wants to go out of bounds ,
i.e. , greater then high
 0 votes  Reply  Message  Permalink

Manohar Reddy Poreddy 2 years ago


looks, it's more to do with mid+1
 1 vote  Reply  Message  Permalink

Madhuri Batchu a year ago


I still cant understand in which case start>end would be possible,could u pls elaborate
ur explanation
 0 votes  Reply  Message  Permalink

Manohar Reddy Poreddy a year ago


sorry I don't remember anything about seg-tree anymore
 0 votes  Reply  Message  Permalink

Vivek Singh  Edited a year ago


last line of update should be tree[node]+=val*(min(end,r)-max(start,l)+1); ?
as tree[node*2] and tree[node*2+1] are still in process
try this problem it will be clear: http://www.spoj.com/problems/HORRIBLE/
 1 vote  Reply  Message  Permalink

Piyush Kumar 8 months ago


Thanks it helped me!!
 0 votes  Reply  Message  Permalink

Pankaj Hazra  Edited 3 months ago


For those who are wondering why
queryRange(int node, int start, int end, int l, int r)
{
if(start > end or start > r or end < l)
return 0;
...}
lazy node is not checked in queryRange for no overlap while it is always checked in case of
updateRange.
This is somewhat smart approach as in order to query you don't need to propagate values into
the children of
nodes who have no overlap.
This reduces a bit of computation.
you don't need to propagate lazy values because you won't get an answer from that range.
(being very lazy)
However, In case of update range, you must propagate lazy values, because if you update a
left subtree of a node and ignore right subtree(which may have values in lazy tree ,
When you combine
you get a wrong answer because you used a node which had lazy values.

for e.g
lets say we have an array A[]={ 1 , 2 , 3 , 4 }
building range sum tree

10
/\
37
/\/\
1234
lets update range (0 ,3 ) with 1
tree now
14
/\
37
/\/\
1234
and lazy tree
0
/\
11
/\/\
0000
lets update (0,1) with 1
so now if you don't consider overlap you will
get a tree like
14
/\
77 ?
/\/\
1234
3 + (1*2) from above lazy left node and 1*2 for current update
the merging child 7+7=14
which is wrong because
your lazy tree looks like
0
/\
0 1 so a wrong answer was propagated .
/\/\
2200
Now doing the correct way
Tree would look like
16
/\
79
/\/\
1234
and the lazy tree looks like
0
/\
00
/\/\
2211
It can be cleary seen that
update( 0,3 ) with 1
update (0, 1) with 1
cause update
{ 2 , 2 , 1 ,1 } in the entire range.
which is quite clear from the lazy tree
so, as a smart tip,
Always check for lazy nodes, even if its in a query or update, you will never regret propagating
values to one level ,
unless the cost is very high.
This can only skipped when not in range ,only in query but in updation lazy node updation for
nodes outside
the range is also important.
 1 vote  Reply  Message  Permalink

Hitesh Garg 3 years ago


In Lazy Propagation , you have called two functions update_tree() and query_tree() without
defining them , how this function is working and where is its body????
 0 votes  Reply  Message  Permalink

Akash Sharma  Author 3 years ago


Thanks for point it out. Fixed. :)
 0 votes  Reply  Message  Permalink

Shivasurya S 3 years ago


Really useful :) thanks
 0 votes  Reply  Message  Permalink

Prateek Singh Chauhan 3 years ago


suppose if i have to find min in array using lazy propagation then y don't we do this (end-
start+1) although we directly update value like SegTree[pos]+=LazyTree[pos];
plz help me out
 0 votes  Reply  Message  Permalink

?
Akash Sharma  Author 3 years ago
Answer is quite simple. In RMQ, each node contain only a single element i.e. the minimum
element in the given range while in RSQ, each node contain the sum of all the elements in
the given range.
 0 votes  Reply  Message  Permalink

Prateek Singh Chauhan 3 years ago


got it... Thanks man
 0 votes  Reply  Message  Permalink

Swapnil Lohani 2 years ago


can we also use lazy propogation in case queries are not for adding some number in
the range but some other type like dividing by some number?
 0 votes  Reply  Message  Permalink

Mojtaba Khooryani 3 years ago


very good
can you give examples of using methods?
 0 votes  Reply  Message  Permalink

Okeke Ugochukwu 3 years ago


Poster, nice tutorial. But what i would like to know more is how to qualify a problem as a
candidate for segment tree and i want to know more about the "split and merge" part of
segment tree.
If one can conquer the split and merge part of the problem then that is a big step.
 0 votes  Reply  Message  Permalink

Alex 3 years ago


Are there two different "segment trees"? According to wiki "segment tree is a tree data
structure for storing intervals, or segments. It allows querying which of the stored segments
contain a given point". Seems it slightly different from this one, used for range queries
 0 votes  Reply  Message  Permalink

~(BzzzKzzzB)~ 3 years ago


what are values passed to function call ------> void build(int node, int start, int end) in main
function
 0 votes  Reply  Message  Permalink

Akash Sharma  Author 3 years ago


build(1, 0, N-1);
 0 votes  Reply  Message  Permalink

~(BzzzKzzzB)~ 3 years ago


Thanks for quick reply. But why first parameter is 1 shouldn't it be 0.
 0 votes  Reply  Message  Permalink

Akash Sharma  Author 3 years ago


No..it will be 1. Look at the first diagram for better understanding. We will
basically pass the root node in the build function.
 0 votes  Reply  Message  Permalink

Ashwani Gautam 3 years ago


Yes you are right it should be 0, as it is root node thus it is the first element of
the array tree
 0 votes  Reply  Message  Permalink

Akash Sharma  Author 3 years ago ?


No. In binary tree we consider the indexing from 1. So that the left child will
be 2*i and right child will be 2*i+1. If we consider 0-indexing then left child
will be 2*0 = 0 which is actually the root.
 0 votes  Reply  Message  Permalink

Ashwani Gautam 3 years ago


Technically you are correct, but as you wrote we are implementing
Binary tree as a linear array which are 0 Based indexed, so i still think it
should be 0
 0 votes  Reply  Message  Permalink

Akash Sharma  Author 3 years ago


That depends on us how we start indexing. But if you call the build
with 0 it will end up in an infinite loop.
 0 votes  Reply  Message  Permalink

Ashwani Gautam 3 years ago


Obvioulsy if you use 0 over there then you have to change
things from 2*i, 2*i+1 to 2*i + 1, 2*i + 2
 0 votes  Reply  Message  Permalink

Bhagwat kumar Singh 3 years ago


Hi friends Help needed.
I have tried to solve this question by Segment tree by lazy propagation (not needed but for
practice) but only able to get 10 marks and getting run time error as well as time limit exceeded
in different cases.
my code is :
https://code.hackerearth.com/9f0941N
 0 votes  Reply  Message  Permalink

Bhagwat kumar Singh 3 years ago


Question 2 : Roy and coin boxes
 0 votes  Reply  Message  Permalink

Saswat Kumar Mishra 3 years ago


On a completely different subject, shouldn't "end" variable be highlighted in black. Because, it's
just a variable like start, node etc. I think you should check the syntax highlighter it may be
taking "end" as a keyword.
 0 votes  Reply  Message  Permalink

Akash Sharma  Author 3 years ago


its because end is a keyword :P :D
 0 votes  Reply  Message  Permalink

Sandeep Ravindra 2 years ago


Great tutorial :D
 0 votes  Reply  Message  Permalink

Shubham Marathia 2 years ago


Thanks mate for such nicely explained tutorial. Hoping to see more like this from you in near
future :P
Can you do one more like this on Maximum sum in range using segtree please ? It would be
totally awesome learning experience for all of us.
 0 votes  Reply  Message  Permalink

Sughosh Kaushik 2 years ago ?


In the update function of the segment tree(without lazy propagation), shouldn't the if condition
be if(start == end && start == idx) ?
 0 votes  Reply  Message  Permalink

Aditya Agarwal 2 years ago


Great source to learn (y)
 0 votes  Reply  Message  Permalink

Mayank Agarwal 2 years ago


How can i generate all possible subsets in the given range (l,r) ?
 0 votes  Reply  Message  Permalink

Sourabh Khandelwal a year ago


Use Backtracking. The problem of generating all subsets of a subset is similar to generating
all the permutations of a string.
 0 votes  Reply  Message  Permalink

Omar Yasser 2 years ago


Thank you ver much :)
 0 votes  Reply  Message  Permalink

Harshal Garg 2 years ago


in the pseudocode for update, shouldn't this be outside else in the main body
tree[node] = tree[2*node] + tree[2*node+1]; ?
please explain
 0 votes  Reply  Message  Permalink

Akash Sharma  Author 2 years ago


No. if start == end that means we are at leaf node. else we are at some interior node and
tree[node] = tree[2*node] + tree[2*node+1]; is only for interior nodes which have a left and
right child.
 0 votes  Reply  Message  Permalink

Harshal Garg 2 years ago


got that.. thanks.. :)
 0 votes  Reply  Message  Permalink

Helper 2 years ago


Nice tutorial..!! Can you please help me solve the "Roy an Coin Boxes Problem" using segment
trees.?
 0 votes  Reply  Message  Permalink

SHUBHAM GUPTA 2 years ago


can anyone tell the what is wrong with my
solution...https://www.hackerearth.com/submission/4521850/
 0 votes  Reply  Message  Permalink

Bihan Sen 2 years ago


I have a query about the function updateRange using Lazy Propagation.
Suppose i want to update the whole array by a value,
then the function call would be updateRange(1,0,n-1,0,n-1,v)
In the first level call of the function it enters to the 3rd if block, updates the root and returns.
I guess the stored lazy values are adjusted during queries, right?
 0 votes  Reply  Message  Permalink

Saeem Ahamed 2 years ago ?


Shouldn't the tree array start with index of Zero0, and so that the left child will be (2*node+1)
and the right child will be (2*node+2)
 0 votes  Reply  Message  Permalink

Manohar Reddy Poreddy 2 years ago


see this: https://www.hackerearth.com/messages/compose/r3gz3n/
 0 votes  Reply  Message  Permalink

Saeem Ahamed 2 years ago


this is not directing to any valid info. its opening up a messaging page. :-(
 0 votes  Reply  Message  Permalink

Manohar Reddy Poreddy 2 years ago


In the comments, above
look for a discussion that is started by "bzzzkzzzb" user, it ends up what you said.
the comment thread above says:
both are possible
1-based and 0-based
If 0-based index then as you said it will be 2i+1 and 2i+2
if 1-based index then, then it will be 2i & 2i+1, most probably 1st element (A[0]) is
not used in array,
 0 votes  Reply  Message  Permalink

Abhishek Bhatt 2 years ago


in query()
return tree[node] condition should have r>=end
or else segmentation error creeps in
 0 votes  Reply  Message  Permalink

Manohar Reddy Poreddy 2 years ago


looks like it is there or is updated now
 0 votes  Reply  Message  Permalink

Juan Fiorenzano 2 years ago


Great article+++++
 0 votes  Reply  Message  Permalink

Mohit Vachhani 2 years ago


What can we do if we have to update the values in the range with the different values.
For example
Suppose Array to be
14234
and then it should be updated by its smallest divisor.
so update range is from 1 to 3
new array would be
12234
What should we do in this case?
 0 votes  Reply  Message  Permalink

Jaskaran Singh 2 years ago


In Lazy Propagation,
What does lazy[k] store?
All the pending updates to the kth node?
You should elaborate this with an example.
The rest of the tutoarial is great and very easy to understand.
 0 votes  Reply  Message  Permalink
?
Sarthak Gupta 2 years ago
What will be the complexity of update function of segment tree (not lazy propagation) if we are
updating from [L,R] .
Will it be (R-L)log(n) or log(n+(R-L))?
 0 votes  Reply  Message  Permalink

Uppinder Chugh 2 years ago


(R-L)logn
 0 votes  Reply  Message  Permalink

Shikhar Jindal 2 years ago


What will be the time complexity for the updateRange function without lazy propagation??
 0 votes  Reply  Message  Permalink

Sai Sharath  Edited 2 years ago


O(nlogn) forr each update
 0 votes  Reply  Message  Permalink

alok gupta 2 years ago


why trere is end-start+1 ?
 0 votes  Reply  Message  Permalink

don't worry 2 years ago


"There are N leaves representing the N elements of the array. The number of internal nodes is
N-1. So total number of nodes are 2*N - 1" whether it means that size of segment tree would
be 2*n-1 ?
 0 votes  Reply  Message  Permalink

Manveer Singh 2 years ago


In that "Another naive solution:" heading, you may also write that ,the making of cumulative
sum array is itself O(N) complexity.
 0 votes  Reply  Message  Permalink

Foyaz Akanda a year ago


awesome article
 0 votes  Reply  Message  Permalink

Subham a year ago


Thank you Hackerearth and Akash Sharma for this wonderful article. It made me understand
segtree thoroughly. Just keep on doing your great work.
 0 votes  Reply  Message  Permalink

Zaid Alkhateeb a year ago


the complex of update range is O(n) because you reach to the son of all node
 0 votes  Reply  Message  Permalink

Bhushan Dhodi  Edited a year ago


Build tree is wrong! Left sub tree is not built! I get this output 36 27 16 11 7 9 0 0 0 0 0 for
given example..please help With what initial parameters should we call build function?
 0 votes  Reply  Message  Permalink

Hrudai pabbisetty a year ago


build(1,0,n-1);
 0 votes  Reply  Message  Permalink

Hrudai pabbisetty a year ago


?
Building the segment tree is top-down right?
 0 votes  Reply  Message  Permalink

Adarsh Kumar a year ago


The 2nd practice problem "Roy and Coin Boxes" mentioned above is nowhere related to
Segment Tree. I can't understand why it is here..
 0 votes  Reply  Message  Permalink

Filipe Herculano a year ago


The complexity of build is more accurate if we say it is O(n * log n) ?
 0 votes  Reply  Message  Permalink

suman 7 months ago


Total no of node in segment tree will be 2*n-1
But we must have segment tree array of 4*n
 0 votes  Reply  Message  Permalink

Mahendra suthar 6 months ago


good work bro:)
 0 votes  Reply  Message  Permalink

Shubham Aggarwal 6 months ago


For query operation, suppose we query for 4-5, our query would first fall at 3 - 5 so it would
return sum of 3 + 4 + 5, but we wanted 4+5 only. How are we taking care of this?
 0 votes  Reply  Message  Permalink

Kunal Kadian 5 months ago


in the updateRange function why is this necessary - >
"If current segment tree node has any pending update, then first add that pending update to
current node."
 0 votes  Reply  Message  Permalink

 AUTHOR

Akash Sharma
 Problem Curator at Hacker…
 Dehradun
 7 notes

TRENDING NOTES

Python Diaries Chapter 3 Map | Filter | For-


else | List Comprehension
written by Divyanshu Bansal

Bokeh | Interactive Visualization Library |


Use Graph with Django Template
written by Prateek Kumar

Bokeh | Interactive Visualization Library |


Graph Plotting
written by Prateek Kumar ?
Python Diaries chapter 2
written by Divyanshu Bansal

Python Diaries chapter 1


written by Divyanshu Bansal
more ...

About Us Innovation Management Technical Recruitment

University Program Developers Wiki Blog

Press Careers Reach Us

Site Language: English | Terms and Conditions | Privacy |© 2018 HackerEarth

You might also like