Reference for point update + range query problems. Java has no built-in segment tree — use this template and read .sum, .max, or .min from the query result.
Related:
17-my-calendar-iii.mdsolves calendar peak overlap with a sweep line. Use a segment tree when you needO(log n)point updates and range queries on a dense index range.
When to use
| Tool | Good for |
|---|---|
| Prefix sum / difference array | Static array, few updates, re-sweep OK |
| Sweep line + TreeMap | Sparse timeline, peak overlap (see #17) |
| Segment tree | Point update + range sum / max / min query |
Use a segment tree when operations are online (many updates and queries) and re-scanning the array each time is too slow.
Core idea
- Binary tree over array indices — each node covers interval
[l, r] - Each node stores an aggregate of its segment (here: sum, max, min)
- Query
[ql, qr]: recurse; fully covered node → return its aggregate; no overlap → return neutral; partial → merge left + right results - Point update: recurse to the target leaf, then merge back up the path
Query cases
Case 1 — total overlap: ql <= l && r <= qr → return tree[index]
Case 2 — no overlap: r < ql || l > qr → return Node.neutral()
Case 3 — partial overlap: recurse both children → Node.merge(left, right)
Both query and update are O(log n).
Java Solution — Segment Tree Template
class SegmentTree {
static class Node {
int sum, max, min;
Node(int sum, int max, int min) {
this.sum = sum;
this.max = max;
this.min = min;
}
static Node neutral() {
return new Node(0, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
static Node merge(Node left, Node right) {
return new Node(
left.sum + right.sum,
Math.max(left.max, right.max),
Math.min(left.min, right.min)
);
}
}
private Node[] tree;
private int n;
public SegmentTree(int[] input) {
this.n = input.length;
this.tree = new Node[4 * n];
buildTree(input, 0, 0, n - 1);
}
private void buildTree(int[] input, int index, int l, int r) {
if (l == r) {
tree[index] = new Node(input[l], input[l], input[l]);
return;
}
int mid = l + (r - l) / 2;
buildTree(input, 2 * index + 1, l, mid);
buildTree(input, 2 * index + 2, mid + 1, r);
tree[index] = Node.merge(tree[2 * index + 1], tree[2 * index + 2]);
}
public Node query(int ql, int qr) {
return query(0, 0, n - 1, ql, qr);
}
private Node query(int index, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) {
return tree[index];
}
if (r < ql || l > qr) {
return Node.neutral();
}
int mid = l + (r - l) / 2;
Node leftResult = query(2 * index + 1, l, mid, ql, qr);
Node rightResult = query(2 * index + 2, mid + 1, r, ql, qr);
return Node.merge(leftResult, rightResult);
}
public void update(int targetIdx, int newValue) {
update(0, 0, n - 1, targetIdx, newValue);
}
private void update(int index, int l, int r, int targetIdx, int newValue) {
if (l == r) {
tree[index] = new Node(newValue, newValue, newValue);
return;
}
int mid = l + (r - l) / 2;
if (targetIdx <= mid) {
update(2 * index + 1, l, mid, targetIdx, newValue);
} else {
update(2 * index + 2, mid + 1, r, targetIdx, newValue);
}
tree[index] = Node.merge(tree[2 * index + 1], tree[2 * index + 2]);
}
}
Why Node.neutral() matters
Partial queries only hit one side of the tree. The untouched side must not pollute the merge — sum = 0, max = -∞, min = +∞ keeps Node.merge correct.
Example — Range Sum Query Mutable (LC 307)
LeetCode 307 — point update, range sum query. Use .sum from the query result.
class NumArray {
private final SegmentTree st;
public NumArray(int[] nums) {
st = new SegmentTree(nums);
}
public void update(int index, int val) {
st.update(index, val);
}
public int sumRange(int left, int right) {
return st.query(left, right).sum;
}
}
Need range max or min on the same array? Same tree — use .max or .min:
int rangeMax = st.query(left, right).max;
int rangeMin = st.query(left, right).min;
Example — Range Max Query
Same template, no code changes — only read a different field:
// max in nums[left..right]
int ans = st.query(left, right).max;
Problems like “max in range after point updates” use the identical tree.
Cheat sheet
| Problem | Read from query(l, r) |
Update |
|---|---|---|
| LC 307 Range Sum Query Mutable | .sum |
point set |
| Range max after point updates | .max |
point set |
| Range min after point updates | .min |
point set |
For range add over [l, r] (many cells at once), this template needs lazy propagation — out of scope here; use sweep line (#17) when that fits instead.
Why It Teaches You Something
One segment tree answers sum, max, and min — the only change at call sites is which field you read. The pattern to memorize:
- Build — leaf = single element, internal =
Node.merge(children) - Query — total overlap / no overlap / partial merge
- Update — walk to leaf, merge back up
That skeleton covers most interview segment tree problems that use point update + range query.