Segment Tree with Lazy Propagation in Java

A segment tree supports efficient range updates and queries over an array. The following implementation uses an explicit tree structure with lazy propagation.

Node Representation

Each node stores its interval boundaries, the aggregated sum, and a pending lazy value that needs to be propagated to its childran before any further traversal.

static class Node {
    int start, end;
    long sum, pending;
}

Node[] tree;
long[] base;

Building the Tree

Build recursively from the oriignal array.

void build(int idx, int l, int r) {
    tree[idx] = new Node();
    tree[idx].start = l;
    tree[idx].end = r;
    tree[idx].pending = 0;
    if (l == r) {
        tree[idx].sum = base[l];
        return;
    }
    int m = (l + r) >> 1;
    build(idx << 1, l, m);
    build(idx << 1 | 1, m + 1, r);
    tree[idx].sum = tree[idx << 1].sum + tree[idx << 1 | 1].sum;
}

Pushing Down Lazy Updates

Apply pending updates to children and reset the current node’s pending flag.

void pushDown(int idx) {
    if (tree[idx].pending == 0) return;
    long tag = tree[idx].pending;
    int leftIdx = idx << 1;
    int rightIdx = leftIdx | 1;
    tree[leftIdx].pending += tag;
    tree[rightIdx].pending += tag;
    int m = (tree[idx].start + tree[idx].end) >> 1;
    tree[leftIdx].sum += tag * (m - tree[leftIdx].start + 1);
    tree[rightIdx].sum += tag * (tree[rightIdx].end - m);
    tree[idx].pending = 0;
}

Range Addition

Add a value delta to all elements in the range [ql, qr].

void rangeAdd(int idx, int ql, int qr, long delta) {
    if (tree[idx].start >= ql && tree[idx].end <= qr) {
        tree[idx].sum += delta * (tree[idx].end - tree[idx].start + 1);
        tree[idx].pending += delta;
        return;
    }
    pushDown(idx);
    if (tree[idx << 1].end >= ql)
        rangeAdd(idx << 1, ql, qr, delta);
    if (tree[idx << 1 | 1].start <= qr)
        rangeAdd(idx << 1 | 1, ql, qr, delta);
    tree[idx].sum = tree[idx << 1].sum + tree[idx << 1 | 1].sum;
}

Range Sum Query

Return the sum of elements in [ql, qr].

long querySum(int idx, int ql, int qr) {
    if (tree[idx].start >= ql && tree[idx].end <= qr)
        return tree[idx].sum;
    pushDown(idx);
    long res = 0;
    if (tree[idx << 1].end >= ql)
        res += querySum(idx << 1, ql, qr);
    if (tree[idx << 1 | 1].start <= qr)
        res += querySum(idx << 1 | 1, ql, qr);
    return res;
}

Always call pushDown before recursing into children to keep lazy values consistent.

Tags: java segment-tree data-structures lazy-propagation

Posted on Sat, 30 May 2026 00:47:09 +0000 by bran