Segment Tree

O(log n) per query

Point updates and range queries over any associative operation (min, max, sum, gcd, ...). This is the compact iterative (bottom-up) version. Swap the two combine lines to change the operation. Reach for it when a Fenwick tree isn't enough (min/max, non-invertible operations).

// use it on

CSES: Dynamic Range Minimum Queries

Point assignments mixed with range-minimum queries. Replace the + combine with min and it's done.

// the code

struct SegTree {  // point update, range query on [l, r)
    int n;
    vector<long long> t;
    SegTree(int n) : n(n), t(2 * n, 0) {}
    void update(int i, long long v) {  // set a[i] = v
        for (t[i += n] = v; i > 1; i >>= 1)
            t[i >> 1] = t[i] + t[i ^ 1];  // combine
    }
    long long query(int l, int r) {  // fold over [l, r)
        long long res = 0;  // identity of the combine
        for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if (l & 1) res += t[l++];
            if (r & 1) res += t[--r];
        }
        return res;
    }
};