templates/lazy-segment-tree.cpp
compilable
$cat templates/lazy-segment-tree
Lazy Segment Tree
Segment tree with lazy propagation — supports range updates and range queries in O(log n).
#segment-tree#lazy-propagation#range-update#range-query
Log in to track progress, save custom versions, and organize into collections.Log In
$cat source_code/
cpp
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 2e5 + 5;
ll tree[4 * MAXN], lazy[4 * MAXN];
ll IDENTITY = 0, LAZY_ID = 0;
int n;
ll combine(ll a, ll b) { return a + b; }
ll apply(ll val, ll lz, int len) { return val + lz * len; }
ll compose(ll old_lz, ll new_lz) { return old_lz + new_lz; }
void pushDown(int idx, int lx, int rx) {
if (lazy[idx] == LAZY_ID) return;
int mid = (lx + rx) / 2;
tree[2 * idx] = apply(tree[2 * idx], lazy[idx], mid - lx + 1);
lazy[2 * idx] = compose(lazy[2 * idx], lazy[idx]);
tree[2 * idx + 1] = apply(tree[2 * idx + 1], lazy[idx], rx - mid);
lazy[2 * idx + 1] = compose(lazy[2 * idx + 1], lazy[idx]);
lazy[idx] = LAZY_ID;
}
void build(ll a[], int idx, int lx, int rx) {
if (lx == rx) { tree[idx] = a[lx]; return; }
int mid = (lx + rx) / 2;
build(a, 2 * idx, lx, mid);
build(a, 2 * idx + 1, mid + 1, rx);
tree[idx] = combine(tree[2 * idx], tree[2 * idx + 1]);
}
void build(ll a[]) { build(a, 1, 1, n); }
void update(int l, int r, ll val, int idx, int lx, int rx) {
if (lx > r || rx < l) return;
if (lx >= l && rx <= r) {
tree[idx] = apply(tree[idx], val, rx - lx + 1);
lazy[idx] = compose(lazy[idx], val);
return;
}
pushDown(idx, lx, rx);
int mid = (lx + rx) / 2;
update(l, r, val, 2 * idx, lx, mid);
update(l, r, val, 2 * idx + 1, mid + 1, rx);
tree[idx] = combine(tree[2 * idx], tree[2 * idx + 1]);
}
void update(int l, int r, ll val) { update(l, r, val, 1, 1, n); }
ll query(int l, int r, int idx, int lx, int rx) {
if (lx > r || rx < l) return IDENTITY;
if (lx >= l && rx <= r) return tree[idx];
pushDown(idx, lx, rx);
int mid = (lx + rx) / 2;
return combine(query(l, r, 2 * idx, lx, mid),
query(l, r, 2 * idx + 1, mid + 1, rx));
}
ll query(int l, int r) { return query(l, r, 1, 1, n); }59 linesutf-8
$cat explanation_notes.md
notes_viewer --renderedmarkdown (math enabled)
Lazy Segment Tree
Extends segment tree to handle range updates by deferring work. Each node stores both a value and a lazy tag.
How It Works
-
combine(a, b) — merge two children-
apply(val, lz, len) — apply lazy to node value-
compose(old, new) — merge two lazy tagsCommon Variants
combine = a + b, apply = val + lz * len, compose = old + newcombine = min(a, b), apply = lz, compose = newcombine = max(a, b), apply = val + lz, compose = old + new