# 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 occurrence 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
- Queries for number of distinct elements in a subarray | Set 2
- Maximize the subarray sum after multiplying all elements of any subarray with X
- Smallest subarray with k distinct numbers
- Maximum Subarray Sum using Divide and Conquer algorithm
- Maximum distinct elements after removing k elements
- Sum of distinct elements when elements are in range 1 to n
- Subarrays with distinct elements
- XOR of a subarray (range of elements)
- Distinct adjacent elements in an array
- Check if all array elements are distinct
- Count distinct elements in an array
- Length of the longest Subarray with only Even Elements
- Maximum Subarray Sum after inverting at most two elements
- Smallest subarray such that all elements are greater than K

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.