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. |
3 1 2
Time complexity: O(N + Q*Log(N))
Space Complexity: O(N*log(N))
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!