Segment Trees Extremely versatile
Basic Segment Tree void add(int pos, int val); int range_sum(int start, int end); Three ways below of visualizing it. Commonly stored in an array to save memory. Node i: Parent = i/2, left child = i *2, right child= i*
Add/Modify Add a certain value to bottom node. Propagate up the tree. Original segment tree-> Add 5 to value 5. New value is 10. Add 5 to every node along the path from the bottom node to the root. Changed nodes are highlighted
Add/Modify Code Note that SIZE is the size of the segment tree (We usually assume it to be a power of 2. You can always pad it with 0s to make it a power of 2). Also, the tree is stored with the root at node 1, its children at node 2 and 3, and so on… void add(int pos, int val) { //pos is 0-indexed int node = SIZE+pos; while(node > 0) { segTree[node] += val; node /= 2; }
Range Sum Sums up the values in a range. Select O(lgn) nodes to cover the range. Original segment tree. Range sum(1,4) The 3 nodes selected cover the range. Sum of range is sum of highlighted nodes
Range Sum Code Call recursive helper function. int sum(int start, int end) { return sum(1, start, end, 0, SIZE-1); } int sum(int node, int start, int end, int left, int right) { // Case 1: Intervals disjoint if(end<left || right<start) return 0; //Case 2: Current interval inside query interval if(start<=left && right<=end) return segTree[node]; //Case 3: Overlap, recurse on children return sum(node*2, start, end, left, (left+right)/2) + sum(node*2+1, start, end, (left+right)/2+1, right); }
Other operations For example, find minimum in range. void add(int pos, int val); int range_min(int start, int end); Add/modify code similar. Basically, a node’s value needs to be computed in O(1) time from its children
Lazy Propagation What if you need to modify a range? You need to BE LAZY! Store lazy value for each node. For updates, find the O(lgn) nodes that cover a range, and set their lazy value. Propagate lazy value to children when recursing on child nodes.
Lazy Propagation Let lazy[node] = value to be added to this interval. True value of node = segTree[node] + lazy[node] at all times (need to be able to determine true value of node from segTree and lazy in O(1) time). Example below: Add 5 to range [0,5]. Highlighted nodes are in range and modified. Can modify lazy and segTree or only lazy
Potw Farmer John has a large field of grass. Each of the N plots has a certain amount of grass. Bessie and the other cows choose an interval in which they want to graze. If Bessie and the cows graze on an interval, the amounts of grass in all plots in that interval are reduced by a certain amount. The cows can’t graze on an interval if it would cause the amount of grass to turn negative, so Farmer John must stop them. How many groups of cows does Farmer John need to stop?
Potw Input format: o Line 1: N C (N is the number of plots of grass and C is the number of groups of cows) o Line 2…N+1: G_i: The amount of grass in the i-th plot o Line N+2…N+C+1: A B C (If the cows graze, they decrease the amount of grass of each plot in [A, B] by C) Output format: o Line 1: A, the amount of groups of cows FJ has to turn away Constraints: o 1<=N,C<=1,000: 10 points o 1<=N,C<=100,000: 25 points Sample input: o 4 3 o 7 o 3 o 2 o 4 o o o Sample output: o 1