# Queries for number of distinct elements in a subarray | Set 2

Last Updated : 06 Apr, 2023

Given an array arr[] of N integers and Q queries. Each query can be represented by two integers L and R. The task is to find the count of distinct integers in the subarray arr[L] to arr[R].
Examples:

Input: arr[] = {1, 1, 3, 3, 5, 5, 7, 7, 9, 9 }, L = 0, R = 4
Output: 3
Input: arr[] = { 1, 1, 2, 1, 3 }, L = 1, R = 3
Output :

Naive approach: In this approach, we will traverse through the range l, r, and use a set to find all the distinct elements in the range and print them.
Time Complexity: O(q*n)
Efficient approach: Idea is to form a segment tree in which the nodes will store all the distinct elements in the range. For this purpose, we can use a self-balancing BST or “set” data structure in C++.
Each query will return the size of the set.
Below is the implementation of the above approach:

## C++

 `// C++ implementation of above approach` `#include ` `using` `namespace` `std;`   `// Each segment of the segment tree would be a set` `// to maintain distinct elements` `set<``int``>* segment;`   `// Build the segment tree` `// i denotes current node, s denotes start and` `// e denotes the end of range for current node` `void` `build(``int` `i, ``int` `s, ``int` `e, ``int` `arr[])` `{`   `    ``// If start is equal to end then` `    ``// insert the array element` `    ``if` `(s == e) {` `        ``segment[i].insert(arr[s]);` `        ``return``;` `    ``}`   `    ``// Else divide the range into two halves` `    ``// (start to mid) and (mid+1 to end)` `    ``// first half will be the left node` `    ``// and the second half will be the right node` `    ``build(2 * i, s, (s + e) / 2, arr);` `    ``build(1 + 2 * i, 1 + (s + e) / 2, e, arr);`   `    ``// Insert the sets of right and left` `    ``// node of the segment tree` `    ``segment[i].insert(segment[2 * i].begin(),` `                      ``segment[2 * i].end());`   `    ``segment[i].insert(segment[2 * i + 1].begin(),` `                      ``segment[2 * i + 1].end());` `}`   `// Query in an range a to b` `set<``int``> query(``int` `node, ``int` `l, ``int` `r, ``int` `a, ``int` `b)` `{` `    ``set<``int``> left, right, result;`   `    ``// If the range is out of the bounds` `    ``// of this segment` `    ``if` `(b < l || a > r)` `        ``return` `result;`   `    ``// If the range lies in this segment` `    ``if` `(a <= l && r <= b)` `        ``return` `segment[node];`   `    ``// Else query for the right and left` `    ``// leaf node of this subtree` `    ``// and insert them into the set` `    ``left = query(2 * node, l, (l + r) / 2, a, b);` `    ``result.insert(left.begin(), left.end());`   `    ``right = query(1 + 2 * node, 1 + (l + r) / 2, r, a, b);` `    ``result.insert(right.begin(), right.end());`   `    ``// Return the result` `    ``return` `result;` `}`   `// Initialize the segment tree` `void` `init(``int` `n)` `{` `    ``// Get the height of the segment tree` `    ``int` `h = (``int``)``ceil``(log2(n));` `    ``h = (2 * (``pow``(2, h))) - 1;`   `    ``// Initialize the segment tree` `    ``segment = ``new` `set<``int``>[h];` `}`   `// Function to get the result for the` `// subarray from arr[l] to arr[r]` `void` `getDistinct(``int` `l, ``int` `r, ``int` `n)` `{` `    ``// Query for the range set` `    ``set<``int``> ans = query(1, 0, n - 1, l, r);`   `    ``cout << ans.size() << endl;` `}`   `// Driver code` `int` `main()` `{`   `    ``int` `arr[] = { 1, 1, 2, 1, 3 };` `    ``int` `n = ``sizeof``(arr) / ``sizeof``(arr[0]);`   `    ``init(n);`   `    ``// Build the segment tree` `    ``build(1, 0, n - 1, arr);`   `    ``// Query in range 0 to 4` `    ``getDistinct(0, 4, n);`   `    ``return` `0;` `}`

## Java

 `// Java implementation of above approach ` `import` `java.io.*;` `import` `java.util.*;`   `class` `GFG` `{`   `    ``// Each segment of the segment tree would be a set` `    ``// to maintain distinct elements` `    ``static` `HashSet[] segment;`   `    ``// Build the segment tree` `    ``// i denotes current node, s denotes start and` `    ``// e denotes the end of range for current node` `    ``static` `void` `build(``int` `i, ``int` `s, ``int` `e, ``int``[] arr)` `    ``{`   `        ``// If start is equal to end then` `        ``// insert the array element` `        ``if` `(s == e)` `        ``{` `            ``segment[i].add(arr[s]);` `            ``return``;` `        ``}`   `        ``// Else divide the range into two halves` `        ``// (start to mid) and (mid+1 to end)` `        ``// first half will be the left node` `        ``// and the second half will be the right node` `        ``build(``2` `* i, s, (s + e) / ``2``, arr);` `        ``build(``1` `+ ``2` `* i, ``1` `+ (s + e) / ``2``, e, arr);`   `        ``// Insert the sets of right and left` `        ``// node of the segment tree` `        ``segment[i].addAll(segment[``2` `* i]);` `        ``segment[i].addAll(segment[``2` `* i + ``1``]);` `    ``}`   `    ``// Query in an range a to b` `    ``static` `HashSet query(``int` `node, ``int` `l, ` `                                ``int` `r, ``int` `a, ``int` `b)` `    ``{` `        ``HashSet left = ``new` `HashSet<>();` `        ``HashSet right = ``new` `HashSet<>();` `        ``HashSet result = ``new` `HashSet<>();`   `        ``// If the range is out of the bounds` `        ``// of this segment` `        ``if` `(b < l || a > r)` `            ``return` `result;`   `        ``// If the range lies in this segment` `        ``if` `(a <= l && r <= b)` `            ``return` `segment[node];`   `        ``// Else query for the right and left` `        ``// leaf node of this subtree` `        ``// and insert them into the set` `        ``left = query(``2` `* node, l, (l + r) / ``2``, a, b);` `        ``result.addAll(left);`   `        ``right = query(``1` `+ ``2` `* node, ``1` `+ (l + r) / ``2``, r, a, b);` `        ``result.addAll(right);`   `        ``// Return the result` `        ``return` `result;` `    ``}`   `    ``// Initialize the segment tree` `    ``@SuppressWarnings``(``"unchecked"``)` `    ``static` `void` `init(``int` `n) ` `    ``{`   `        ``// Get the height of the segment tree` `        ``int` `h = (``int``) Math.ceil(Math.log(n) / Math.log(``2``));` `        ``h = (``int``) (``2` `* Math.pow(``2``, h)) - ``1``;`   `        ``// Initialize the segment tree` `        ``segment = ``new` `HashSet[h];` `        ``for` `(``int` `i = ``0``; i < h; i++)` `            ``segment[i] = ``new` `HashSet<>();` `    ``}`   `    ``// Function to get the result for the` `    ``// subarray from arr[l] to arr[r]` `    ``static` `void` `getDistinct(``int` `l, ``int` `r, ``int` `n)` `    ``{`   `        ``// Query for the range set` `        ``HashSet ans = query(``1``, ``0``, n - ``1``, l, r);`   `        ``System.out.println(ans.size());` `    ``}`   `    ``// Driver Code` `    ``public` `static` `void` `main(String[] args)` `    ``{` `        ``int``[] arr = { ``1``, ``1``, ``2``, ``1``, ``3` `};` `        ``int` `n = arr.length;`   `        ``init(n);`   `        ``// Build the segment tree` `        ``build(``1``, ``0``, n - ``1``, arr);`   `        ``// Query in range 0 to 4` `        ``getDistinct(``0``, ``4``, n);` `    ``}` `}`   `// This code is contributed by` `// sanjeev2552`

## Python3

 `# python3 implementation of above approach` `from` `math ``import` `ceil,log,floor`   `# Each segment of the segment tree would be a set` `# to maintain distinct elements` `segment``=``[[] ``for` `i ``in` `range``(``1000``)]`   `# Build the segment tree` `# i denotes current node, s denotes start and` `# e denotes the end of range for current node` `def` `build(i, s, e, arr):`   `    ``# If start is equal to end then` `    ``# append the array element` `    ``if` `(s ``=``=` `e):` `        ``segment[i].append(arr[s])` `        ``return`   `    ``# Else divide the range into two halves` `    ``# (start to mid) and (mid+1 to end)` `    ``# first half will be the left node` `    ``# and the second half will be the right node` `    ``build(``2` `*` `i, s, (s ``+` `e) ``/``/` `2``, arr)` `    ``build(``1` `+` `2` `*` `i, ``1` `+` `(s ``+` `e) ``/``/` `2``, e, arr)`   `    ``# Insert the sets of right and left` `    ``# node of the segment tree` `    ``segment[i].append(segment[``2` `*` `i])`   `    ``segment[i].append(segment[``2` `*` `i ``+` `1``])`   `# Query in an range a to b` `def` `query(node, l, r, a, b):` `    ``left, right, result``=``[],[],[]`   `    ``# If the range is out of the bounds` `    ``# of this segment` `    ``if` `(b < l ``or` `a > r):` `        ``return` `result`   `    ``# If the range lies in this segment` `    ``if` `(a <``=` `l ``and` `r <``=` `b):` `        ``return` `segment[node]`   `    ``# Else query for the right and left` `    ``# leaf node of this subtree` `    ``# and append them into the set` `    ``left ``=` `query(``2` `*` `node, l, (l ``+` `r) ``/``/` `2``, a, b)` `    ``result.append(left)`   `    ``right ``=` `query(``1` `+` `2` `*` `node, ``1` `+` `(l ``+` `r) ``/``/` `2``, r, a, b)` `    ``result.append(right)`   `    ``# Return the result` `    ``return` `result` `def` `answer(ans):` `    ``d ``=` `{}` `    ``for` `i ``in` `str``(ans):` `        ``if` `i ``not` `in` `[``'['``,``','``,``']'``,``' '``]:` `            ``d[i]``=``1` `    ``return` `len``(d)`   `# Initialize the segment tree` `def` `init(n):` `    `  `    ``# Get the height of the segment tree` `    ``h ``=` `ceil(log(n, ``2``))` `    ``h ``=` `(``2` `*` `(``pow``(``2``, h))) ``-` `1`   `# Function to get the result for the` `# subarray from arr[l] to arr[r]` `def` `getDistinct(l, r, n):` `    `  `    ``# Query for the range set` `    ``ans ``=` `query(``1``, ``0``, n ``-` `1``, l, r)`   `    ``print``(answer(``str``(ans)))`   `# Driver code` `arr``=``[``1``, ``1``, ``2``, ``1``, ``3``]` `n ``=` `len``(arr)`   `init(n)`   `# Build the segment tree` `build(``1``, ``0``, n ``-` `1``, arr)`   `# Query in range 0 to 4` `getDistinct(``0``, ``4``, n)`   `# This code is contributed by mohit kumar 29`

## C#

 `// C# implementation of ` `// the above approach ` `using` `System;` `using` `System.Collections;` `using` `System.Collections.Generic; ` `class` `GFG{` ` `  `// Each segment of the segment` `// tree would be a set to maintain ` `// distinct elements` `static` `HashSet<``int``>[] segment;` ` `  `// Build the segment tree` `// i denotes current node, ` `// s denotes start and` `// e denotes the end of ` `// range for current node` `static` `void` `build(``int` `i, ``int` `s, ` `                  ``int` `e, ``int``[] arr)` `{` `  ``// If start is equal to end then` `  ``// insert the array element` `  ``if` `(s == e)` `  ``{` `    ``segment[i].Add(arr[s]);` `    ``return``;` `  ``}`   `  ``// Else divide the range ` `  ``// into two halves (start ` `  ``// to mid) and (mid+1 to end)` `  ``// first half will be the left ` `  ``// node and the second half ` `  ``// will be the right node` `  ``build(2 * i, s, ` `        ``(s + e) / 2, arr);` `  ``build(1 + 2 * i, ` `        ``1 + (s + e) / 2, ` `        ``e, arr);`   `  ``// Insert the sets of ` `  ``// right and left node ` `  ``// of the segment tree` `  ``foreach``(``int` `x ``in` `segment[2 * i])` `  ``{` `    ``segment[i].Add(x);    ` `  ``}`   `  ``foreach``(``int` `x ``in` `segment[2 * i + 1])` `  ``{` `    ``segment[i].Add(x);    ` `  ``}` `}` ` `  `// Query in an range a to b` `static` `HashSet<``int``> query(``int` `node, ``int` `l, ` `                          ``int` `r, ``int` `a, ``int` `b)` `{` `  ``HashSet<``int``> left = ``new` `HashSet<``int``>();` `  ``HashSet<``int``> right = ``new` `HashSet<``int``>();` `  ``HashSet<``int``> result = ``new` `HashSet<``int``>();`   `  ``// If the range is out ` `  ``// of the bounds` `  ``// of this segment` `  ``if` `(b < l || a > r)` `    ``return` `result;`   `  ``// If the range lies ` `  ``// in this segment` `  ``if` `(a <= l && r <= b)` `    ``return` `segment[node];`   `  ``// Else query for the right and left` `  ``// leaf node of this subtree` `  ``// and insert them into the set` `  ``left = query(2 * node,` `               ``l, (l + r) / 2, ` `               ``a, b);` `  ``foreach``(``int` `x ``in` `left)` `  ``{` `    ``result.Add(x);    ` `  ``}`   `  ``right = query(1 + 2 * node,` `                ``1 + (l + r) / 2, ` `                ``r, a, b);` `  ``foreach``(``int` `x ``in` `right)` `  ``{` `    ``result.Add(x);    ` `  ``}`   `  ``// Return the result` `  ``return` `result;` `}`   `// Initialize the segment tree` `static` `void` `init(``int` `n) ` `{`   `  ``// Get the height of the segment tree` `  ``int` `h = (``int``) Math.Ceiling(Math.Log(n) / ` `                             ``Math.Log(2));` `  ``h = (``int``) (2 * Math.Pow(2, h)) - 1;`   `  ``// Initialize the segment tree` `  ``segment = ``new` `HashSet<``int``>[h];` `  `  `  ``for` `(``int` `i = 0; i < h; i++)` `    ``segment[i] = ``new` `HashSet<``int``>();` `}`   `// Function to get the result for the` `// subarray from arr[l] to arr[r]` `static` `void` `getDistinct(``int` `l, ` `                        ``int` `r, ``int` `n)` `{ ` `  ``// Query for the range set` `  ``HashSet<``int``> ans = query(1, 0, ` `                           ``n - 1, ` `                           ``l, r);`   `  ``Console.Write(ans.Count);` `}`   `// Driver Code` `public` `static` `void` `Main(``string``[] args)` `{` `  ``int``[] arr = {1, 1, 2, 1, 3};` `  ``int` `n = arr.Length;` `  ``init(n);`   `  ``// Build the segment tree` `  ``build(1, 0, n - 1, arr);`   `  ``// Query in range 0 to 4` `  ``getDistinct(0, 4, n);` `}` `}`   `// This code is contributed by rutvik_56`

## Javascript

 ``

Output:

`3`

Time Complexity: O(q*n*log(n)), where n is the size of the input array.

Auxiliary space: O(n*log(n)), as the segment tree has 2n-1 nodes and each node contains a set of distinct elements.

Previous
Next