guest@itl:~/home/range-queries$
templates/sqrt-decomposition.cpp
compilable
$cat templates/sqrt-decomposition

SQRT Decomposition

Square root decomposition with sorted blocks for range counting queries and point updates in O(sqrt n).

#sqrt-decomposition#bucket#range-query#sorted-blocks
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;
int a[MAXN], n, blockSz;
vector<int> blocks[450];

void build() {
    blockSz = max(1, (int)sqrt(n));
    for (int i = 0; i < n; i++)
        blocks[i / blockSz].push_back(a[i]);
    for (int i = 0; i <= n / blockSz; i++)
        sort(blocks[i].begin(), blocks[i].end());
}

void update(int idx, int val) {
    int bi = idx / blockSz;
    auto &blk = blocks[bi];
    blk.erase(lower_bound(blk.begin(), blk.end(), a[idx]));
    a[idx] = val;
    blk.insert(lower_bound(blk.begin(), blk.end(), val), val);
}

int query(int l, int r, int x) {
    int res = 0;
    while (l <= r && l % blockSz != 0)
        res += a[l++] >= x;
    while (l + blockSz - 1 <= r) {
        auto &blk = blocks[l / blockSz];
        res += blk.end() - lower_bound(blk.begin(), blk.end(), x);
        l += blockSz;
    }
    while (l <= r)
        res += a[l++] >= x;
    return res;
}
37 linesutf-8
$cat explanation_notes.md
notes_viewer --renderedmarkdown (math enabled)

SQRT Decomposition

Partition an array of nn elements into B=nB = \lceil\sqrt{n}\rceil blocks, each stored in sorted order. Enables range counting queries and point updates in O(n)O(\sqrt{n}).

How It Works

  • Element at index ii goes into block i/B\lfloor i / B \rfloor

  • Each block is sorted to allow binary search

  • Query (count elements x\ge x in [l,r][l, r]):

  • - Left/right partial blocks — scan linearly
    - Full blocks — binary search for xx, count elements x\ge x
  • Update — overwrite value, re-sort the affected block
  • When to Use

  • Range counting queries like "count elements k\ge k in [l,r][l, r]"

  • Simpler alternative to segment tree when O(n)O(\sqrt{n}) per operation is acceptable

  • Problems with point updates + range queries that don't need O(logn)O(\log n)
  • Complexity

  • Build — O(nlogn)O(n \log n)

  • Query — O(n)O(\sqrt{n})

  • Point update — O(n)O(\sqrt{n})

  • Space — O(n)O(n)