# Working and need of Mo’s Aalgorithm

**Mo’s Algorithm** is a generic algorithm. It can be used in many problems that require processing range queries in a static array, i.e., the array values do not change between the queries. In each query, for a given range **[a, b]** the idea is to calculate the value based on the array elements between positions of **a** and **b**. Since the array is static, the queries can be processed in any order, and **Mo’s Algorithm** processes the queries in a special order which guarantees that the algorithm works efficiently.

It maintains an **active range** of the array, and the result of a query concerning the **active range** is known at each moment. The algorithm processes the queries one by one, and always moves the endpoints of the active range by inserting and removing elements.

**Time Complexity:***O(N√N*f(N))*, where the array has **N*** *elements and there are **N*** *queries and each insertion and removal of an element takes * O(f(N))* time.

The trick in Mo’s algorithm is the order in which the queries are processed:

- The array is divided into blocks of k = O(√N) elements, and a query
**[a**is processed before a query_{1}, b_{1}]**[a**if either_{2}, b_{2}]**[a**] or_{1}/k] < [a_{2}/k**[a1/k] = [a2/k]**and**b**_{1}< b_{2}_{ }is true. - Thus, all queries whose left endpoints are in a certain block are processed one after another sorted according to their right endpoints.
- Using this order, the algorithm only performs
*O(N√N)*operations, because of the left endpoint moves*O(N)*times*O(√N)*steps, and the right endpoint moves*O(√N)*times*O(N)*steps. - Thus, both endpoints move a total of
*O(N√N)*steps during the algorithm.

**Example:** Consider a problem where there are given a set of queries, each of them corresponding to a range in an array, and the task is to calculate for each query the number of **distinct **elements in the range. In Mo’s algorithm, the queries are always sorted in the same way, but it depends on the problem of how the answer to the query is maintained.

- In this problem, the idea is to maintain an array
**count[]****count[x]**indicates the number of times an element**x**occurs in the active range. - When moving from one query to another query, the active range changes. For example, if the current range is {4,
**2, 5, 4, 2**, 4, 3, 3, 4} and the next range is {4, 2,**5, 4, 2, 4, 3**, 3, 4}. (ranges are marked as bold) - There will be three steps: the left endpoint moves one step to the right, and the right endpoint moves two steps to the right.
- After each step, the array
**count[]** - After adding an element
**x**, increase the value of**count[x]**by**1**, and if the**count[x] = 1**after this also increase the answer to the query by**1**. - Similarly, after removing an element
**x**, decrease the value of**count[x]**by**1**, and if the**count[x] = 0**after this, also decrease the answer to the query by**1**. - In this problem, the time needed to perform each step is
*O(1)*, so the total time complexity of the algorithm is*O(N√N)*.

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the **DSA Self Paced Course** at a student-friendly price and become industry ready. To complete your preparation from learning a language to DS Algo and many more, please refer **Complete Interview Preparation Course****.**

In case you wish to attend **live classes **with experts, please refer **DSA Live Classes for Working Professionals **and **Competitive Programming Live for Students**.