Home
DSA Visualizer
Advanced Topics
Introduction to Mo's Algorithm
Introduction to Mo's Algorithm
Mo's algorithm starts from the problem of offline range queries and the intuition behind square root decomposition.
ARRIVAL ORDER
MOVED 10
L
R
POINTER TRAVEL
10
Queries, in processing order
Query 1 covers [0, 10]. The pointers had to move 10 steps to get here — running total 10.
Next
Query 2 covers [8, 9]. The pointers had to move 9 steps to get here — running total 19.
Order
Intuition
We are given an array and many queries (L, R) asking for the sum (or other property) in that range.
If we answer queries as they come, our pointers might jump wildly from the beginning to the end of the array, wasting time. What if we could re-arrange the queries to "smooth out" the movement?
Concept
Sorting Queries:
- Divide indices into buckets of size
sqrt(N). - Sort queries by their Left Bucket Index.
- If in the same bucket, sort by Right Index.
This simple trick ensures L moves slowly (within a bucket) and R sweeps back and forth efficiently.
How it Works
The visualizer compares Naive Order vs Mo's Order.
- Naive: The pointers (blue bars) jump erratically across the array. Total distance is huge.
- Mo's: The pointers move in a controlled snake-like pattern. Total distance is minimized.
Step-by-Step Breakdown
1. Identify the block size B = sqrt(N).
2. Assign each query a block_id = L / B.
3. Sort queries: Primary logic block_id, Secondary logic R.
4. Process sequentially.
When to Use
- Offline Range Queries.
- You can't use Segment Tree (e.g., computing Mode frequency).
When NOT to Use
- Online queries (must answer immediately).
- Updates to array values (Mo's is static usually).
How to Identify
"Range queries", "Static Array", "Offline processing allowed".
Applying for software engineering roles? Free, no sign-up:
