Open In App

Find the count of distinct numbers in a range

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array of size N containing numbers only from 0 to 63, and you are asked Q queries regarding it.
Queries are as follows: 
 

  • 1 X Y i.e Change the element at index X to Y
  • 2 L R i.e Print the count of distinct elements present in between L and R inclusive

Examples: 
 

Input:
N = 7
ar = {1, 2, 1, 3, 1, 2, 1}
Q = 5
{ {2, 1, 4},
  {1, 4, 2},
  {1, 5, 2},
  {2, 4, 6},
  {2, 1, 7} }
Output:
3
1
2

Input:
N = 15
ar = {4, 6, 3, 2, 2, 3, 6, 5, 5, 5, 4, 2, 1, 5, 1}
Q = 5
{ {1, 6, 5},
  {1, 4, 2},
  {2, 6, 14},
  {2, 6, 8},
  {2, 1, 6} };

Output:
5
2
5

 

Pre-requisites: Segment Tree and Bit Manipulation 
Approach:
 

  • The bitMask formed in the question will denote the presence of ith number or not, we will find out that by checking the ith bit of our bitMask, if the ith bit is on, that means i’th element is present, otherwise not present.
  • Build a classical segment tree and each of its nodes will contain a bitmask which is used to decode the number of distinct elements in that particular segment which is defined by the particular node.
  • Build the segment Tree in a bottom-up manner, therefore the bitMask for the current node of the segment tree can be easily calculated by performing bitwise OR operation on the bitMasks of this node’s right and left child. Leaf nodes will be handled separately. Updation will also be done in the same manner.

Below is the implementation of the above approach: 
 

C++




// C++ Program to find the distinct
// elements in a range
#include <bits/stdc++.h>
using namespace std;
 
// Function to perform queries in a range
long long query(int start, int end, int left, int right,
                int node, long long seg[])
{
    // No overlap
    if (end < left || start > right) {
        return 0;
    }
 
    // Totally Overlap
    else if (start >= left && end <= right) {
        return seg[node];
    }
 
    // Partial Overlap
    else {
        int mid = (start + end) / 2;
 
        // Finding the Answer
        // for the left Child
        long long leftChild = query(start, mid, left,
                                    right, 2 * node, seg);
 
        // Finding the Answer
        // for the right Child
        long long rightChild = query(mid + 1, end, left,
                                     right, 2 * node + 1, seg);
 
        // Combining the BitMasks
        return (leftChild | rightChild);
    }
}
 
// Function to perform update operation
// in the Segment seg
void update(int left, int right, int index, int Value,
            int node, int ar[], long long seg[])
{
    if (left == right) {
        ar[index] = Value;
 
        // Forming the BitMask
        seg[node] = (1LL << Value);
        return;
    }
 
    int mid = (left + right) / 2;
    if (index > mid) {
 
        // Updating the left Child
        update(mid + 1, right, index, Value, 2 * node + 1, ar, seg);
    }
    else {
 
        // Updating the right Child
        update(left, mid, index, Value, 2 * node, ar, seg);
    }
 
    // Updating the BitMask
    seg[node] = (seg[2 * node] | seg[2 * node + 1]);
}
 
// Building the Segment Tree
void build(int left, int right, int node, int ar[],
           long long seg[])
{
    if (left == right) {
 
        // Building the Initial BitMask
        seg[node] = (1LL << ar[left]);
 
        return;
    }
 
    int mid = (left + right) / 2;
 
    // Building the left seg tree
    build(left, mid, 2 * node, ar, seg);
 
    // Building the right seg tree
    build(mid + 1, right, 2 * node + 1, ar, seg);
 
    // Forming the BitMask
    seg[node] = (seg[2 * node] | seg[2 * node + 1]);
}
 
// Utility Function to answer the queries
void getDistinctCount(vector<vector<int> >& queries,
                      int ar[], long long seg[], int n)
{
 
    for (int i = 0; i < queries.size(); i++) {
 
        int op = queries[i][0];
 
        if (op == 2) {
 
            int l = queries[i][1], r = queries[i][2];
 
            long long tempMask = query(0, n - 1, l - 1,
                                       r - 1, 1, seg);
 
            int countOfBits = 0;
 
            // Counting the set bits which denote the
            // distinct elements
            for (int i = 63; i >= 0; i--) {
 
                if (tempMask & (1LL << i)) {
 
                    countOfBits++;
                }
            }
 
            cout << countOfBits << '\n';
        }
        else {
 
            int index = queries[i][1];
            int val = queries[i][2];
 
            // Updating the value
            update(0, n - 1, index - 1, val, 1, ar, seg);
        }
    }
}
 
// Driver Code
int main()
{
    int n = 7;
    int ar[] = { 1, 2, 1, 3, 1, 2, 1 };
 
    long long seg[4 * n] = { 0 };
    build(0, n - 1, 1, ar, seg);
 
    int q = 5;
    vector<vector<int> > queries = {
        { 2, 1, 4 },
        { 1, 4, 2 },
        { 1, 5, 2 },
        { 2, 4, 6 },
        { 2, 1, 7 }
    };
 
    getDistinctCount(queries, ar, seg, n);
 
    return 0;
}


Java




// Java Program to find the distinct
// elements in a range
import java.util.*;
 
class GFG{
  
// Function to perform queries in a range
static long query(int start, int end, int left, int right,
                int node, long seg[])
{
    // No overlap
    if (end < left || start > right) {
        return 0;
    }
  
    // Totally Overlap
    else if (start >= left && end <= right) {
        return seg[node];
    }
  
    // Partial Overlap
    else {
        int mid = (start + end) / 2;
  
        // Finding the Answer
        // for the left Child
        long leftChild = query(start, mid, left,
                                    right, 2 * node, seg);
  
        // Finding the Answer
        // for the right Child
        long rightChild = query(mid + 1, end, left,
                                     right, 2 * node + 1, seg);
  
        // Combining the BitMasks
        return (leftChild | rightChild);
    }
}
  
// Function to perform update operation
// in the Segment seg
static void update(int left, int right, int index, int Value,
            int node, int ar[], long seg[])
{
    if (left == right) {
        ar[index] = Value;
  
        // Forming the BitMask
        seg[node] = (1L << Value);
        return;
    }
  
    int mid = (left + right) / 2;
    if (index > mid) {
  
        // Updating the left Child
        update(mid + 1, right, index, Value, 2 * node + 1, ar, seg);
    }
    else {
  
        // Updating the right Child
        update(left, mid, index, Value, 2 * node, ar, seg);
    }
  
    // Updating the BitMask
    seg[node] = (seg[2 * node] | seg[2 * node + 1]);
}
  
// Building the Segment Tree
static void build(int left, int right, int node, int ar[],
           long seg[])
{
    if (left == right) {
  
        // Building the Initial BitMask
        seg[node] = (1L << ar[left]);
  
        return;
    }
  
    int mid = (left + right) / 2;
  
    // Building the left seg tree
    build(left, mid, 2 * node, ar, seg);
  
    // Building the right seg tree
    build(mid + 1, right, 2 * node + 1, ar, seg);
  
    // Forming the BitMask
    seg[node] = (seg[2 * node] | seg[2 * node + 1]);
}
  
// Utility Function to answer the queries
static void getDistinctCount(int  [][]queries,
                      int ar[], long seg[], int n)
{
  
    for (int i = 0; i < queries.length; i++) {
  
        int op = queries[i][0];
  
        if (op == 2) {
  
            int l = queries[i][1], r = queries[i][2];
  
            long tempMask = query(0, n - 1, l - 1,
                                       r - 1, 1, seg);
  
            int countOfBits = 0;
  
            // Counting the set bits which denote the
            // distinct elements
            for (int s = 63; s >= 0; s--) {
  
                if ((tempMask & (1L << s))>0) {
  
                    countOfBits++;
                }
            }
  
            System.out.println(countOfBits);
        }
        else {
  
            int index = queries[i][1];
            int val = queries[i][2];
  
            // Updating the value
            update(0, n - 1, index - 1, val, 1, ar, seg);
        }
    }
}
  
// Driver Code
public static void main(String[] args)
{
    int n = 7;
    int ar[] = { 1, 2, 1, 3, 1, 2, 1 };
  
    long seg[] = new long[4 * n];
    build(0, n - 1, 1, ar, seg);
  
    int [][]queries = {
        { 2, 1, 4 },
        { 1, 4, 2 },
        { 1, 5, 2 },
        { 2, 4, 6 },
        { 2, 1, 7 }
    };
  
    getDistinctCount(queries, ar, seg, n);
  
}
}
 
// This code is contributed by PrinciRaj1992


Python3




# Python3 Program to find the distinct
# elements in a range
 
# Function to perform queries in a range
def query(start, end, left,
          right, node, seg):
     
    # No overlap
    if (end < left or start > right):
        return 0
 
    # Totally Overlap
    elif (start >= left and
            end <= right):
        return seg[node]
 
    # Partial Overlap
    else:
        mid = (start + end) // 2
 
        # Finding the Answer
        # for the left Child
        leftChild = query(start, mid, left,
                          right, 2 * node, seg)
 
        # Finding the Answer
        # for the right Child
        rightChild = query(mid + 1, end, left,
                           right, 2 * node + 1, seg)
 
        # Combining the BitMasks
        return (leftChild | rightChild)
 
# Function to perform update operation
# in the Segment seg
def update(left, right, index,
           Value, node, ar, seg):
    if (left == right):
        ar[index] = Value
 
        # Forming the BitMask
        seg[node] = (1 << Value)
        return
 
    mid = (left + right) // 2
    if (index > mid):
 
        # Updating the left Child
        update(mid + 1, right, index,
               Value, 2 * node + 1, ar, seg)
    else:
 
        # Updating the right Child
        update(left, mid, index,
               Value, 2 * node, ar, seg)
 
    # Updating the BitMask
    seg[node] = (seg[2 * node] |
                 seg[2 * node + 1])
 
# Building the Segment Tree
def build(left, right, node, ar, eg):
 
    if (left == right):
 
        # Building the Initial BitMask
        seg[node] = (1 << ar[left])
 
        return
 
    mid = (left + right) // 2
 
    # Building the left seg tree
    build(left, mid, 2 * node, ar, seg)
 
    # Building the right seg tree
    build(mid + 1, right,
                2 * node + 1, ar, seg)
 
    # Forming the BitMask
    seg[node] = (seg[2 * node] |
                 seg[2 * node + 1])
 
# Utility Function to answer the queries
def getDistinctCount(queries, ar, seg, n):
 
    for i in range(len(queries)):
 
        op = queries[i][0]
 
        if (op == 2):
 
            l = queries[i][1]
            r = queries[i][2]
 
            tempMask = query(0, n - 1, l - 1,
                             r - 1, 1, seg)
 
            countOfBits = 0
 
            # Counting the set bits which denote
            # the distinct elements
            for i in range(63, -1, -1):
 
                if (tempMask & (1 << i)):
 
                    countOfBits += 1
 
            print(countOfBits)
        else:
 
            index = queries[i][1]
            val = queries[i][2]
 
            # Updating the value
            update(0, n - 1, index - 1,
                       val, 1, ar, seg)
 
# Driver Code
if __name__ == '__main__':
    n = 7
    ar = [1, 2, 1, 3, 1, 2, 1]
 
    seg = [0] * 4 * n
    build(0, n - 1, 1, ar, seg)
 
    q = 5
    queries = [[ 2, 1, 4 ],
               [ 1, 4, 2 ],
               [ 1, 5, 2 ],
               [ 2, 4, 6 ],
               [ 2, 1, 7 ]]
 
    getDistinctCount(queries, ar, seg, n)
 
# This code is contributed by Mohit Kumar


C#




// C# Program to find the distinct
// elements in a range
using System;
 
class GFG{
   
// Function to perform queries in a range
static long query(int start, int end, int left, int right,
                int node, long []seg)
{
    // No overlap
    if (end < left || start > right) {
        return 0;
    }
   
    // Totally Overlap
    else if (start >= left && end <= right) {
        return seg[node];
    }
   
    // Partial Overlap
    else {
        int mid = (start + end) / 2;
   
        // Finding the Answer
        // for the left Child
        long leftChild = query(start, mid, left,
                                    right, 2 * node, seg);
   
        // Finding the Answer
        // for the right Child
        long rightChild = query(mid + 1, end, left,
                                     right, 2 * node + 1, seg);
   
        // Combining the BitMasks
        return (leftChild | rightChild);
    }
}
   
// Function to perform update operation
// in the Segment seg
static void update(int left, int right, int index, int Value,
            int node, int []ar, long []seg)
{
    if (left == right) {
        ar[index] = Value;
   
        // Forming the BitMask
        seg[node] = (1L << Value);
        return;
    }
   
    int mid = (left + right) / 2;
    if (index > mid) {
   
        // Updating the left Child
        update(mid + 1, right, index, Value, 2 * node + 1, ar, seg);
    }
    else {
   
        // Updating the right Child
        update(left, mid, index, Value, 2 * node, ar, seg);
    }
   
    // Updating the BitMask
    seg[node] = (seg[2 * node] | seg[2 * node + 1]);
}
   
// Building the Segment Tree
static void build(int left, int right, int node, int []ar,
           long []seg)
{
    if (left == right) {
   
        // Building the Initial BitMask
        seg[node] = (1L << ar[left]);
   
        return;
    }
   
    int mid = (left + right) / 2;
   
    // Building the left seg tree
    build(left, mid, 2 * node, ar, seg);
   
    // Building the right seg tree
    build(mid + 1, right, 2 * node + 1, ar, seg);
   
    // Forming the BitMask
    seg[node] = (seg[2 * node] | seg[2 * node + 1]);
}
   
// Utility Function to answer the queries
static void getDistinctCount(int  [,]queries,
                      int []ar, long []seg, int n)
{
   
    for (int i = 0; i < queries.GetLength(0); i++) {
   
        int op = queries[i,0];
   
        if (op == 2) {
   
            int l = queries[i,1], r = queries[i,2];
   
            long tempMask = query(0, n - 1, l - 1,
                                       r - 1, 1, seg);
   
            int countOfBits = 0;
   
            // Counting the set bits which denote the
            // distinct elements
            for (int s = 63; s >= 0; s--) {
   
                if ((tempMask & (1L << s))>0) {
   
                    countOfBits++;
                }
            }
   
            Console.WriteLine(countOfBits);
        }
        else {
   
            int index = queries[i,1];
            int val = queries[i,2];
   
            // Updating the value
            update(0, n - 1, index - 1, val, 1, ar, seg);
        }
    }
}
   
// Driver Code
public static void Main(String[] args)
{
    int n = 7;
    int []ar = { 1, 2, 1, 3, 1, 2, 1 };
   
    long []seg = new long[4 * n];
    build(0, n - 1, 1, ar, seg);
   
    int [,]queries = {
        { 2, 1, 4 },
        { 1, 4, 2 },
        { 1, 5, 2 },
        { 2, 4, 6 },
        { 2, 1, 7 }
    };
   
    getDistinctCount(queries, ar, seg, n);
   
}
}
 
// This code is contributed by 29AjayKumar


Javascript




class GFG
{
    // Function to perform queries in a range
    static query(start, end, left, right, node, seg)
    {
        // No overlap
        if (end < left || start > right)
        {
            return 0;
        }
        else if (start >= left && end <= right)
        {
            return seg[node];
        }
        else
        {
            var mid = parseInt((start + end) / 2);
             
            // Finding the Answer
            // for the left Child
            var leftChild = GFG.query(start, mid, left, right, 2 * node, seg);
             
            // Finding the Answer
            // for the right Child
            var rightChild = GFG.query(mid + 1, end, left, right, 2 * node + 1, seg);
             
            // Combining the BitMasks
            return (leftChild | rightChild);
        }
    }
    // Function to perform update operation
    // in the Segment seg
    static update(left, right, index, Value, node, ar, seg)
    {
        if (left == right)
        {
            ar[index] = Value;
             
            // Forming the BitMask
            seg[node] = (1 << Value);
            return;
        }
        var mid = parseInt((left + right) / 2);
        if (index > mid)
        {
            // Updating the left Child
            GFG.update(mid + 1, right, index, Value, 2 * node + 1, ar, seg);
        }
        else
        {
            // Updating the right Child
            GFG.update(left, mid, index, Value, 2 * node, ar, seg);
        }
         
        // Updating the BitMask
        seg[node] = (seg[2 * node] | seg[2 * node + 1]);
    }
     
    // Building the Segment Tree
    static build(left, right, node, ar, seg)
    {
        if (left == right)
        {
         
            // Building the Initial BitMask
            seg[node] = (1 << ar[left]);
            return;
        }
        var mid = parseInt((left + right) / 2);
         
        // Building the left seg tree
        GFG.build(left, mid, 2 * node, ar, seg);
         
        // Building the right seg tree
        GFG.build(mid + 1, right, 2 * node + 1, ar, seg);
         
        // Forming the BitMask
        seg[node] = (seg[2 * node] | seg[2 * node + 1]);
    }
     
    // Utility Function to answer the queries
    static getDistinctCount(queries, ar, seg, n)
    {
        for (var i = 0; i < queries.length; i++)
        {
            var op = queries[i][0];
            if (op == 2)
            {
                var l = queries[i][1];
                var r = queries[i][2];
                var tempMask = GFG.query(0, n - 1, l - 1, r - 1, 1, seg);
                var countOfBits = 0;
                 
                // Counting the set bits which denote the
                // distinct elements
                for (var s = 32; s >= 0; s--)
                {
                    if ((tempMask & (1 << s)) > 0)
                    {
                        countOfBits++;
                    }
                }
                console.log(countOfBits+"<br>");
            }
            else
            {
                var index = queries[i][1];
                var val = queries[i][2];
                 
                // Updating the value
                GFG.update(0, n - 1, index - 1, val, 1, ar, seg);
            }
        }
    }
     
    // Driver Code
    static main(args)
    {
        var n = 7;
        var ar = [1, 2, 1, 3, 1, 2, 1];
        var seg = Array(4 * n).fill(0);
        GFG.build(0, n - 1, 1, ar, seg);
        var queries = [[2, 1, 4], [1, 4, 2], [1, 5, 2], [2, 4, 6], [2, 1, 7]];
        GFG.getDistinctCount(queries, ar, seg, n);
    }
}
GFG.main([]);
 
// This code is contributed by aadityaburujwale.


Output: 

3
1
2

 

Time complexity: O(N + Q*Log(N))
Space Complexity: O(N*log(N))



Last Updated : 27 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads