A segment tree where each node stores the sorted list of the elements in its range. Answers “how many elements in are ” in .

Construction

vector<vector<int>> tree_;                      // tree_[node] = sorted elements of its range
 
void build(int node, int l, int r, vector<int>& a) {
    if (l == r) { tree_[node] = {a[l]}; return; }
    int m = (l + r) / 2;
    build(2*node, l, m, a);
    build(2*node+1, m+1, r, a);
    tree_[node].resize(r - l + 1);
    merge(tree_[2*node].begin(), tree_[2*node].end(),
          tree_[2*node+1].begin(), tree_[2*node+1].end(),
          tree_[node].begin());
}

Build is time and memory — each element appears once per level.

Query

int countLE(int node, int l, int r, int ql, int qr, int x) {
    if (qr < l || r < ql) return 0;
    if (ql <= l && r <= qr)
        return upper_bound(tree_[node].begin(), tree_[node].end(), x) - tree_[node].begin();
    int m = (l + r) / 2;
    return countLE(2*node, l, m, ql, qr, x) + countLE(2*node+1, m+1, r, ql, qr, x);
}

nodes, each with an binary search → .

Fractional cascading

Storing, in each node, the position each element maps to in its children removes the repeated binary search — the child’s position follows from the parent’s in . That gives per query.

The bookkeeping is significant and the constant improvement is modest; it is rarely worth writing in a contest, but it is the standard example of the fractional cascading technique.

What it answers

QueryMethod
Count of elements in upper_bound per node
Count in a value range in difference of two counts
-th smallest in binary search the answer + count,
Smallest element in lower_bound per node, take the min
Number of distinct values✘ — use a different structure

The competitors

StructureBuildQueryUpdatesMemory
Merge sort tree
Merge sort tree + fractional cascading
Persistent segment tree
Wavelet tree bits
BIT of sorted vectors
Offline BIT sweep am.
Mo’s algorithm
Sqrt decomposition + sorted blocks✔ (rebuild a block)

Prefer the offline sweep

If the queries are known in advance — which they nearly always are — sort by value and sweep with a plain BIT over positions. time, memory, and it supports point updates. That beats a merge sort tree on every axis.

Persistent segment trees are the right choice when the queries must be online and you need the -th smallest.

Supporting updates

Replacing an element requires re-sorting every node on its root path — per update in the worst case. If updates are needed:

  • Point updates + range count → offline BIT sweep, or a sqrt decomposition with sorted blocks (rebuild one block in ).
  • Replace the sorted vector in each node with a multiset or a BIT — updates but a much worse constant and memory of node overhead.

Where it is still the right call

The merge sort tree earns its place when you need online range-count-less-than queries, have no update requirement, and want something you can write correctly in ten minutes. It is simple, hard to get wrong, and is plenty for .

See also: Segment Tree · Wavelet Tree · Persistent Structures