# Distinct elements in subarray using Mo’s Algorithm

Given an array ‘a[]’ of size n and number of queries q. Each query can be represented by two integers l and r. Your task is to print the number of distinct integers in the subarray l to r.

Given a[i] <=

Examples :

Input : a[] = {1, 1, 2, 1, 2, 3} q = 3 0 4 1 3 2 5 Output : 2 2 3 In query 1, number of distinct integers in a[0...4] is 2 (1, 2) In query 2, number of distinct integers in a[1..3] is 2 (1, 2) In query 3, number of distinct integers in a[2..5] is 3 (1, 2, 3) Input : a[] = {7, 3, 5, 9, 7, 6, 4, 3, 2} q = 4 1 5 0 4 0 7 1 8 output : 5 4 6 7

Let a[0…n-1] be input array and q[0..m-1] be array of queries.

**Approach :**

- Sort all queries in a way that queries with L values from 0 to are put together, then all queries from to , and so on. All queries within a block are sorted in increasing order of R values.
- Initialize an array freq[] of size with 0 . freq[] array keep count of frequencies of all the elements in lying in a given range.
- Process all queries one by one in a way that every query uses number of different elements and frequency array computed in previous query and stores the result in structure.
- Let ‘curr_Diff_element’ be number of different elements of previous query.
- Remove extra elements of previous query. For example if previous query is [0, 8] and current query is [3, 9], then remove a[0], a[1] and a[2]
- Add new elements of current query. In the same example as above, add a[9].
- Sort the queries in the same order as they were provided earlier and print their stored results

**Adding elements()**

- Increase the frequency of element to be added(freq[a[i]]) by 1.
- If frequency of element a[i] is 1.Increase curr_diff_element by 1 as 1 new element has been added in range.

**Removing elements() **

- Decrease frequency of element to be removed (a[i]) by 1.
- if frequency of an element a[i] is 0.Just decrease curr_diff_element by 1 as 1 element has been completely removed from the range.

**Note : ** In this algorithm, in step 2, index variable for R change at most O(n * ) times throughout the run and same for L changes its value at most O(m * ) times. All these bounds are possible only because sorted queries first in blocks of size.

The preprocessing part takes O(m Log m) time.

Processing all queries takes O(n * ) + O(m * ) = O((m+n) *) time.

**Below is the implementation of above approach :**

`// Program to compute no. of different elements ` `// of ranges for different range queries ` `#include <bits/stdc++.h> ` `using` `namespace` `std; ` ` ` `// Used in frequency array (maximum value of an ` `// array element). ` `const` `int` `MAX = 1000000; ` ` ` `// Variable to represent block size. This is made ` `// global so compare() of sort can use it. ` `int` `block; ` ` ` `// Structure to represent a query range and to store ` `// index and result of a particular query range ` `struct` `Query { ` ` ` `int` `L, R, index, result; ` `}; ` ` ` `// Function used to sort all queries so that all queries ` `// of same block are arranged together and within a block, ` `// queries are sorted in increasing order of R values. ` `bool` `compare(Query x, Query y) ` `{ ` ` ` `// Different blocks, sort by block. ` ` ` `if` `(x.L / block != y.L / block) ` ` ` `return` `x.L / block < y.L / block; ` ` ` ` ` `// Same block, sort by R value ` ` ` `return` `x.R < y.R; ` `} ` ` ` `// Function used to sort all queries in order of their ` `// index value so that results of queries can be printed ` `// in same order as of input ` `bool` `compare1(Query x, Query y) ` `{ ` ` ` `return` `x.index < y.index; ` `} ` ` ` `// calculate distinct elements of all query ranges. ` `// m is number of queries n is size of array a[]. ` `void` `queryResults(` `int` `a[], ` `int` `n, Query q[], ` `int` `m) ` `{ ` ` ` `// Find block size ` ` ` `block = (` `int` `)` `sqrt` `(n); ` ` ` ` ` `// Sort all queries so that queries of same ` ` ` `// blocks are arranged together. ` ` ` `sort(q, q + m, compare); ` ` ` ` ` `// Initialize current L, current R and current ` ` ` `// different elements ` ` ` `int` `currL = 0, currR = 0; ` ` ` `int` `curr_Diff_elements = 0; ` ` ` ` ` `// Initialize frequency array with 0 ` ` ` `int` `freq[MAX] = { 0 }; ` ` ` ` ` `// Traverse through all queries ` ` ` `for` `(` `int` `i = 0; i < m; i++) { ` ` ` ` ` `// L and R values of current range ` ` ` `int` `L = q[i].L, R = q[i].R; ` ` ` ` ` `// Remove extra elements of previous range. ` ` ` `// For example if previous range is [0, 3] ` ` ` `// and current range is [2, 5], then a[0] ` ` ` `// and a[1] are subtracted ` ` ` `while` `(currL < L) { ` ` ` ` ` `// element a[currL] is removed ` ` ` `freq[a[currL]]--; ` ` ` `if` `(freq[a[currL]] == 0) ` ` ` `curr_Diff_elements--; ` ` ` ` ` `currL++; ` ` ` `} ` ` ` ` ` `// Add Elements of current Range ` ` ` `// Note:- during addition of the left ` ` ` `// side elements we have to add currL-1 ` ` ` `// because currL is already in range ` ` ` `while` `(currL > L) { ` ` ` `freq[a[currL - 1]]++; ` ` ` ` ` `// include a element if it occurs first time ` ` ` `if` `(freq[a[currL - 1]] == 1) ` ` ` `curr_Diff_elements++; ` ` ` ` ` `currL--; ` ` ` `} ` ` ` `while` `(currR <= R) { ` ` ` `freq[a[currR]]++; ` ` ` ` ` `// include a element if it occurs first time ` ` ` `if` `(freq[a[currR]] == 1) ` ` ` `curr_Diff_elements++; ` ` ` ` ` `currR++; ` ` ` `} ` ` ` ` ` `// Remove elements of previous range. For example ` ` ` `// when previous range is [0, 10] and current range ` ` ` `// is [3, 8], then a[9] and a[10] are subtracted ` ` ` `// Note:- Basically for a previous query L to R ` ` ` `// currL is L and currR is R+1. So during removal ` ` ` `// of currR remove currR-1 because currR was ` ` ` `// never included ` ` ` `while` `(currR > R + 1) { ` ` ` ` ` `// element a[currL] is removed ` ` ` `freq[a[currR - 1]]--; ` ` ` ` ` `// if ocurrence of a number is reduced ` ` ` `// to zero remove it from list of ` ` ` `// different elements ` ` ` `if` `(freq[a[currR - 1]] == 0) ` ` ` `curr_Diff_elements--; ` ` ` ` ` `currR--; ` ` ` `} ` ` ` `q[i].result = curr_Diff_elements; ` ` ` `} ` `} ` ` ` `// print the result of all range queries in ` `// initial order of queries ` `void` `printResults(Query q[], ` `int` `m) ` `{ ` ` ` `sort(q, q + m, compare1); ` ` ` `for` `(` `int` `i = 0; i < m; i++) { ` ` ` `cout << ` `"Number of different elements"` `<< ` ` ` `" in range "` `<< q[i].L << ` `" to "` ` ` `<< q[i].R << ` `" are "` `<< q[i].result << endl; ` ` ` `} ` `} ` ` ` `// Driver program ` `int` `main() ` `{ ` ` ` `int` `a[] = { 1, 1, 2, 1, 3, 4, 5, 2, 8 }; ` ` ` `int` `n = ` `sizeof` `(a) / ` `sizeof` `(a[0]); ` ` ` `Query q[] = { { 0, 4, 0, 0 }, { 1, 3, 1, 0 }, ` ` ` `{ 2, 4, 2, 0 } }; ` ` ` `int` `m = ` `sizeof` `(q) / ` `sizeof` `(q[0]); ` ` ` `queryResults(a, n, q, m); ` ` ` `printResults(q, m); ` ` ` `return` `0; ` `} ` |

*chevron_right*

*filter_none*

**Output:**

Number of different elements in range 0 to 4 are 3 Number of different elements in range 1 to 3 are 2 Number of different elements in range 2 to 4 are 3

## Recommended Posts:

- Longest subarray not having more than K distinct elements
- Smallest subarray with k distinct numbers
- Maximum distinct elements after removing k elements
- Maximum Subarray Sum using Divide and Conquer algorithm
- Sum of distinct elements when elements are in range 1 to n
- Subarrays with distinct elements
- Count distinct elements in an array
- Distinct adjacent elements in an array
- Check if all array elements are distinct
- XOR of a subarray (range of elements)
- Print All Distinct Elements of a given integer array
- Product of non-repeating (distinct) elements in an Array
- Count distinct elements in every window of size k
- Find sum of non-repeating (distinct) elements in an array
- Third largest element in an array of distinct elements

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.