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


In this problem, we are given an array arr[] of size n and we are given a query. Each query contains two values (L, R). our task is to create a program to solve queries for number of distinct elements in a subarray

Problem description − Here, we will need to find the total number of distinct integers that are present in the subarray from the index (L-1) to (R-1).

Let’s take an example to understand the problem,

Input

arr[] = {4, 6, 1, 3, 1, 6, 5}
query = [1, 4]

Output

4

Explanation

For query 1: L = 1 & R = 4, we need to find the number of the distinct elements from index 0 to 3, which is 4.

For query 2: L = 2 & R = 6, we need to find the number of distinct elements from index 1 to 5, which is 3.

Solution Approach

A simple approach to solve each query is to traverse the array from L to R and store elements to the set, whose size will give the result of the querry. The same we have discussed in the last set.

A more effective way to solve the problem is using the segment tree data structure. It will store the distinct element count for the given range.

A segment tree is a special type of tree, that stores information in the form of segments.

The leaf node of the segment tree denotes the elements of the array. And the non-leaf nodes denote the segments with the required value. Here, it will store the distinct elements. For the implementation of this data structure, we will use Set.

Program to implement the working of above solution −

Example

 Live Demo

#include <bits/stdc++.h>
using namespace std;
set<int>* segmentTree;

void CreateSegmentTree(int i, int s, int e, int arr[]) {

   if (s == e) {
      segmentTree[i].insert(arr[s]);
      return;
   }
   CreateSegmentTree(2 * i, s, (s + e) / 2, arr);
   CreateSegmentTree(1 + 2 * i, 1 + (s + e) / 2, e, arr);
   segmentTree[i].insert( segmentTree[2 * i].begin(), segmentTree[2 * i].end());
   segmentTree[i].insert(segmentTree[2 * i + 1].begin(), segmentTree[2 * i + 1].end());
}

set<int> findDistSubarray(int node, int l, int r, int a, int b) {

   set<int> left, right, distinctSubarray;
   if (b < l || a > r)
   return distinctSubarray;
   if (a <= l && r <= b)
   return segmentTree[node];
   left = findDistSubarray(2 * node, l, (l + r) / 2, a, b);
   distinctSubarray.insert(left.begin(), left.end());
   right = findDistSubarray(1 + 2 * node, 1 + (l + r) / 2, r, a, b);
   return distinctSubarray;
}

int main() {

   int arr[] = {4, 6, 1, 3, 1, 6, 5};
   int n = sizeof(arr) / sizeof(arr[0]);
   int query[] = {1, 4};
   int i = (int)ceil(log2(n));
   i = (2 * (pow(2, i))) - 1;
   segmentTree = new set<int>[i];
   CreateSegmentTree(1, 0, n - 1, arr);
   set<int> distCount = findDistSubarray(1, 0, n - 1, (query[0]-1), (query[1]-1));
   cout<<"The number of distinct elements in the subarray is "<<distCount.size();
   return 0;
}

Output

The number of distinct elements in the subarray is 4

Updated on: 09-Sep-2020

255 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements