Segment tree
Description
-
Segment tree: update one element & query for intervals
-
Segment tree: update intervals & query one element
- the lazy update operations are very important to improve the efficience
- so, PushDown means pushing the laziness down to its’ sub-trees
Code
-
// https://leetcode.com/problems/range-sum-query-mutable/ class NumArray { class ST{ int l, r, val; public ST(int l, int r, int v){ this.l = l; this.r = r; this.val = v; } } ST[] st; private int Left(int x) { return 2 * x + 1; } private int Right(int x) { return 2 * x + 2; } private void build(ST[] st, int stIndex, int[] nums, int l, int r){ if(l == r){ st[stIndex] = new ST(l, r, nums[l]); return ; } int mid = (r - l) / 2 + l; build(st, Left(stIndex), nums, l, mid); build(st, Right(stIndex), nums, mid + 1, r); st[stIndex] = new ST(l, r, st[Left(stIndex)].val + st[Right(stIndex)].val); } private void updateST(int targetIndex, int newValue, ST[] st, int stIndex){ if(st[stIndex].l == st[stIndex].r && st[stIndex].l == targetIndex){ st[stIndex].val = newValue; return ; } int mid = (st[stIndex].r - st[stIndex].l) / 2 + st[stIndex].l; if(targetIndex >= st[stIndex].l && targetIndex <= mid){ updateST(targetIndex, newValue, st, Left(stIndex)); } else { updateST(targetIndex, newValue, st, Right(stIndex)); } st[stIndex] = new ST(st[stIndex].l, st[stIndex].r, st[Left(stIndex)].val + st[Right(stIndex)].val); } private int query(int targetLeft, int targetRight, ST[] st, int stIndex){ if(targetLeft == st[stIndex].l && targetRight == st[stIndex].r){ return st[stIndex].val; } int mid = (st[stIndex].r - st[stIndex].l) /2 + st[stIndex].l; if(targetLeft > mid){ return query(targetLeft, targetRight, st, Right(stIndex)); } else if(targetRight <= mid){ return query(targetLeft, targetRight, st, Left(stIndex)); } else return query(targetLeft, mid, st, Left(stIndex)) + query(mid + 1, targetRight, st, Right(stIndex)); } public NumArray(int[] nums) { if(nums.length > 0){ st = new ST[nums.length << 2]; build(st, 0, nums, 0, nums.length - 1); } } public void update(int i, int val) { updateST(i, val, st, 0); } public int sumRange(int i, int j) { return query(i, j, st, 0); } }
2.
//https://leetcode.com/problems/my-calendar-iii/ class MyCalendarThree { class TreeNode{ int l, r, max, lazy; TreeNode left, right; public TreeNode(int l, int r, int val){ this.l = l; this.r = r; this.max = val; this.lazy = 0; } } TreeNode root; public MyCalendarThree() { root = new TreeNode(0, 1000000000, 0); } private void update(TreeNode rt, int targetLeft, int targetRight){ if(rt.l == targetLeft && rt.r == targetRight){ rt.lazy ++; rt.max ++; return; } if(rt.l == rt.r) return ; int mid = (rt.r - rt.l) / 2 + rt.l; if(rt.left == null){ rt.left = new TreeNode(rt.l, mid, 0); } if(rt.right == null){ rt.right = new TreeNode(mid + 1, rt.r, 0); } // push down if(rt.lazy > 0){ rt.left.lazy += rt.lazy; rt.left.max += rt.lazy; rt.right.lazy += rt.lazy; rt.right.max += rt.lazy; rt.lazy = 0; } if(mid >= targetRight) update(rt.left, targetLeft, targetRight); else if(mid < targetLeft) update(rt.right, targetLeft, targetRight); else { update(rt.left, targetLeft, mid); update(rt.right, mid + 1, targetRight); } // push up rt.max = Math.max(rt.right.max, rt.left.max); } public int book(int start, int end) { update(root, start, end - 1); return root.max; } }