1 / 22
Nov 2010

Hi friends,
can you suggest me a good tutorial for segment tree. i am still unclear about its algorithm and implementation (tutorial need not contain code itself). i went through tutorial given at Topcoder, but it was not in that detail.
Thanks smile

  • created

    Nov '10
  • last reply

    Oct '12
  • 21

    replies

  • 1.7k

    views

  • 7

    users

  • 1

    like

  • 3

    links

I was going to suggest the one on Topcoder since that's where I learned it.

Maybe is there one in the CodeForces blogs?

Are you trying to solve a specific problem with it? Maybe you could explain what you don't understand about it and it could be clarified.

yeah leppy, i am trying to solve Multiple of 3 problem on SPOJ. spoj.pl/problems/MULTQ3/6

what i could not understand is how do i implement the very basic query/update function on segment tree. consider the segment tree of [0,9] on topcoder. if i am to increase the value of elements in range [0,5] by 1, how do i search for this range in tree. moreover each element is present on more than one tree node (for example element 9 is present on the last node at each level), so which tree node out of all those nodes should i increase for that element.
same problem i will face in retrieving value of any range.

I'm going to use a smaller range for simplicity. So the tree looks like this:

                     [1,8]
		 [1,4]                    [5,8]
   [1,2]       [3,4]        [5,6]      [7,8]
[1,1] [2,2] [3,3] [4,4] [5,5] [6,6] [7,7] [8,8]

Each of those nodes stores the information that you're trying to find for that range. If you want to query the range [1,8], you only need to inspect the root node. If you want to query the range [3,5], when at the root you need to split it in to two queries, based on the left and right children of the node. [3,4] and [5,5].

When it comes to updating, you can use the same fashion as above and a term called "lazy propagation". If you were to update range [1,8] you would effectively have to update every node in the tree. Lazy propagation means that you would only update node [1,8] and leave a flag that says that it's children need to be updated. Then when you have to query deeper than [1,8] you push the update down to the children, along with the flag. This way you only update when needed.

thanks leppy. your explanation indeed made things clearer. understanding topcoder's tutorial will be easier now smile
i will get back to you if face problem again. thanks once again smile

ok consider i have to perform following operations on tree.
1: update interval [3,5]
2: query interval [1,4]

1) going down the tree my interval is split in two parts [3,4] and [5,5] so i update these two new ranges and their children (if any). i.e. now [3,4], [3,3], [4,4], [5,5] are updated.

2) here my interval need not split, it is directly the left child of root node and this left child was "not" updated by last operation. so the overlapping interval of [1,4] and [3,5] will still be printed with the old value

When you update [3,4] you have to let the result of the update filter back up to the root.

1 year later

With lazy propagation, how to handle two consecutive update operations?? For example, if i first want to update the root [1,8], then i should update only [1,8] and flag [1,4] and [5,8] . Now if my immediate next operation is to update the interval [5,8], then what would be the necessary things to do?? Please help..

It all depends how you have implemented the tree. What is the value at [5,8]?

If you're solving LITE and the value at [5,8] is 0 then you simply need to turn off the update flag.

8 3
0 1 8
0 5 8
1 5 8

Yes, you are right. I am trying to solve LITE. In each node I'm storing the number of lights that are on within that interval. Actually I'm more bothered about the node[1,4]. When I update [1,8] then [1,4] and [5,8] are flagged. Next if I want to update node [5,8] then should I also update [1,4] (since [1,4] is flagged) and then propagate the result back to [1,8] (by adding the values of [1,4] and [5,8])??

In my implementation, if a flag for a node is on, the value in that node is accurate, but he value for all nodes below it is not. Therefore I would not be worried about [1,4] but if your implementation is different you will need to figure that out.

Or you could cache the value of the node before you update it and subtract the difference after you update it, then you wouldn't have to worry about it. This adds extra constant memory complexity though.

Thanks leppy. Got AC. But with lazy propagation, it is still O(mlogn). It is not asymptotically faster. Is it?? Please correct me, if I'm wrong.

In the worst case it is tons faster. Each query or update takes at worst log(number of nodes). Without lazy propagation each update takes (number of nodes) at the worst.

100000 100000
0 1 100000
0 1 100000
...
...
0 1 100000

Yes. I see. Thanks. smile Without your tutorial on lazy propagation, it won't have been possible for me to solve LITE.

1 month later

thanks leppy. your explanation indeed made things clearer. understanding topcoder's tutorial will be easier now.

7 months later