Balance two costs by choosing a threshold around . The array-splitting version is on Square Root Decomposition; this page covers the other sqrt tricks — the ones that split operations, values or time rather than indices.

1. Sqrt rebuilding — the general escape hatch

Keep a fast static structure plus a small buffer of recent updates.

query  = static_answer + correction_from_buffer     O(fast + |buffer|)
update = append to the buffer                        O(1)
every sqrt(q) updates: rebuild the static structure  O(build)

Amortized per operation. This makes any static structure updatable:

Static structureBecomes
Sorted arrayinsertable “sorted list”
Convex hulldynamic hull
Precomputed tableupdatable table
Sparse tablesupports point updates
Aho-Corasick automatonsupports pattern insertion

The Aho-Corasick case is a nice one: rebuilding the automaton every insertions, and brute-forcing the buffered patterns, gives an “add patterns online” multi-pattern matcher.

2. Heavy/light splitting by frequency

Split objects by a threshold and handle each class differently.

SettingHeavyLight
Values with count at most of them — precompute per heavy valuefew occurrences — brute force
Vertices with degree at most of themiterate their neighbours directly
Patterns with length at most of themgroup by length
Queries with range few of thembrute force

Triangle counting is the classic: orient each edge from lower to higher degree; every vertex then has out-degree , so enumerating pairs of out-neighbours is .

// count triangles in O(m^1.5)
for (auto [u, v] : edges)
    if (make_pair(deg[u], u) < make_pair(deg[v], v)) g[u].push_back(v);
    else g[v].push_back(u);
for (int u = 0; u < n; u++) {
    for (int v : g[u]) mark[v] = 1;
    for (int v : g[u]) for (int w : g[v]) if (mark[w]) triangles++;
    for (int v : g[u]) mark[v] = 0;
}

3. Sqrt on values

When the values are bounded by , split at :

  • small values — maintain a frequency array;
  • large values — there are at most distinct ones with high multiplicity; handle them individually.

Used for “count subsets summing to ” and knapsack variants where the number of distinct item weights is — a genuinely useful observation, since distinct positive weights summing to force .

4. Sqrt on time (operation batching)

Process queries in blocks of :

  • within a block, treat the structure as static and answer with brute force over the block’s updates;
  • at the end of each block, apply all its updates in bulk.

This is the shape of Mo’s algorithm and of many “rebuild periodically” solutions.

Choosing the threshold

is the right answer only when the two sides have equal constants. When updates are much rarer than queries (or vice versa), tune — a 2-3× speedup is typical, and it is often the difference between TLE and AC.

Measure rather than guess: try .

When sqrt techniques are right

per operation with is about — comfortable. At it is and too slow.

Rule of thumb: sqrt methods are for . Their value is that they work when nothing else does — for operations that no tree structure can merge, and for problems whose structure resists -factor solutions.

See also: Square Root Decomposition · Mo’s Algorithm · Offline Query Processing