Array range queries for elements with frequency same as value
Last Updated :
27 Apr, 2023
Given an array of N numbers, the task is to answer Q queries of the following type:
query(start, end) = Number of times a
number x occurs exactly x times in a
subarray from start to end
Examples:
Input : arr = {1, 2, 2, 3, 3, 3}
Query 1: start = 0, end = 1,
Query 2: start = 1, end = 1,
Query 3: start = 0, end = 2,
Query 4: start = 1, end = 3,
Query 5: start = 3, end = 5,
Query 6: start = 0, end = 5
Output : 1 0 2 1 1 3
Explanation:
In Query 1, Element 1 occurs once in subarray [1, 2];
In Query 2, No Element satisfies the required condition is subarray [2];
In Query 3, Element 1 occurs once and 2 occurs twice in subarray [1, 2, 2];
In Query 4, Element 2 occurs twice in subarray [2, 2, 3];
In Query 5, Element 3 occurs thrice in subarray [3, 3, 3];
In Query 6, Element 1 occurs once, 2 occurs twice and 3 occurs thrice in subarray [1, 2, 2, 3, 3, 3]
Method 1 (Brute Force): Calculate frequency of every element in the subarray under each query. If any number x has frequency x in the subarray covered under each query, we increment the counter.
Implementation:
C++
/* C++ Program to answer Q queries to
find number of times an element x
appears x times in a Query subarray */
#include <bits/stdc++.h>
using namespace std;
/* Returns the count of number x with
frequency x in the subarray from
start to end */
int solveQuery(int start, int end, int arr[])
{
// map for frequency of elements
unordered_map<int, int> frequency;
// store frequency of each element
// in arr[start; end]
for (int i = start; i <= end; i++)
frequency[arr[i]]++;
// Count elements with same frequency
// as value
int count = 0;
for (auto x : frequency)
if (x.first == x.second)
count++;
return count;
}
int main()
{
int A[] = { 1, 2, 2, 3, 3, 3 };
int n = sizeof(A) / sizeof(A[0]);
// 2D array of queries with 2 columns
int queries[][3] = { { 0, 1 },
{ 1, 1 },
{ 0, 2 },
{ 1, 3 },
{ 3, 5 },
{ 0, 5 } };
// calculating number of queries
int q = sizeof(queries) / sizeof(queries[0]);
for (int i = 0; i < q; i++) {
int start = queries[i][0];
int end = queries[i][1];
cout << "Answer for Query " << (i + 1)
<< " = " << solveQuery(start,
end, A) << endl;
}
return 0;
}
Java
/* Java Program to answer Q queries to
find number of times an element x
appears x times in a Query subarray */
import java.util.HashMap;
import java.util.Map;
class GFG
{
/* Returns the count of number x with
frequency x in the subarray from
start to end */
static int solveQuery(int start, int end, int arr[])
{
// map for frequency of elements
Map<Integer,Integer> mp = new HashMap<>();
// store frequency of each element
// in arr[start; end]
for (int i = start; i <= end; i++)
mp.put(arr[i],mp.get(arr[i]) == null?1:mp.get(arr[i])+1);
// Count elements with same frequency
// as value
int count = 0;
for (Map.Entry<Integer,Integer> entry : mp.entrySet())
if (entry.getKey() == entry.getValue())
count++;
return count;
}
// Driver code
public static void main(String[] args)
{
int A[] = { 1, 2, 2, 3, 3, 3 };
int n = A.length;
// 2D array of queries with 2 columns
int [][]queries = { { 0, 1 },
{ 1, 1 },
{ 0, 2 },
{ 1, 3 },
{ 3, 5 },
{ 0, 5 } };
// calculating number of queries
int q = queries.length;
for (int i = 0; i < q; i++)
{
int start = queries[i][0];
int end = queries[i][1];
System.out.println("Answer for Query " + (i + 1)
+ " = " + solveQuery(start,
end, A));
}
}
}
// This code is contributed by Rajput-Ji
Python3
# Python 3 Program to answer Q queries
# to find number of times an element x
# appears x times in a Query subarray
import math as mt
# Returns the count of number x with
# frequency x in the subarray from
# start to end
def solveQuery(start, end, arr):
# map for frequency of elements
frequency = dict()
# store frequency of each element
# in arr[start end]
for i in range(start, end + 1):
if arr[i] in frequency.keys():
frequency[arr[i]] += 1
else:
frequency[arr[i]] = 1
# Count elements with same
# frequency as value
count = 0
for x in frequency:
if x == frequency[x]:
count += 1
return count
# Driver code
A = [1, 2, 2, 3, 3, 3 ]
n = len(A)
# 2D array of queries with 2 columns
queries = [[ 0, 1 ], [ 1, 1 ],
[ 0, 2 ], [ 1, 3 ],
[ 3, 5 ], [ 0, 5 ]]
# calculating number of queries
q = len(queries)
for i in range(q):
start = queries[i][0]
end = queries[i][1]
print("Answer for Query ", (i + 1),
" = ", solveQuery(start,end, A))
# This code is contributed
# by Mohit kumar 29
C#
// C# Program to answer Q queries to
// find number of times an element x
// appears x times in a Query subarray
using System;
using System.Collections.Generic;
class GFG
{
/* Returns the count of number x with
frequency x in the subarray from
start to end */
public static int solveQuery(int start,
int end,
int[] arr)
{
// map for frequency of elements
Dictionary<int,
int> mp = new Dictionary<int,
int>();
// store frequency of each element
// in arr[start; end]
for (int i = start; i <= end; i++)
{
if (mp.ContainsKey(arr[i]))
mp[arr[i]]++;
else
mp.Add(arr[i], 1);
}
// Count elements with same frequency
// as value
int count = 0;
foreach (KeyValuePair<int,
int> entry in mp)
{
if (entry.Key == entry.Value)
count++;
}
return count;
}
// Driver code
public static void Main(String[] args)
{
int[] A = { 1, 2, 2, 3, 3, 3 };
int n = A.Length;
// 2D array of queries with 2 columns
int[,] queries = {{ 0, 1 }, { 1, 1 },
{ 0, 2 }, { 1, 3 },
{ 3, 5 }, { 0, 5 }};
// calculating number of queries
int q = queries.Length;
for (int i = 0; i < q; i++)
{
int start = queries[i, 0];
int end = queries[i, 1];
Console.WriteLine("Answer for Query " + (i + 1) +
" = " + solveQuery(start, end, A));
}
}
}
// This code is contributed by
// sanjeev2552
JavaScript
<script>
/* Javascript Program to answer Q queries to
find number of times an element x
appears x times in a Query subarray */
/* Returns the count of number x with
frequency x in the subarray from
start to end */
function solveQuery(start,end,arr)
{
// map for frequency of elements
let mp = new Map();
// store frequency of each element
// in arr[start; end]
for (let i = start; i <= end; i++)
mp.set(arr[i],mp.get(arr[i]) == null?1:mp.get(arr[i])+1);
// Count elements with same frequency
// as value
let count = 0;
for (let [key, value] of mp.entries())
if (key == value)
count++;
return count;
}
// Driver code
let A=[1, 2, 2, 3, 3, 3];
let n = A.length;
// 2D array of queries with 2 columns
let queries = [[ 0, 1 ], [ 1, 1 ],
[ 0, 2 ], [ 1, 3 ],
[ 3, 5 ], [ 0, 5 ]];
// calculating number of queries
let q = queries.length;
for (let i = 0; i < q; i++)
{
let start = queries[i][0];
let end = queries[i][1];
document.write("Answer for Query " + (i + 1)
+ " = " + solveQuery(start,
end, A)+"<br>");
}
// This code is contributed by unknown2108
</script>
OutputAnswer for Query 1 = 1
Answer for Query 2 = 0
Answer for Query 3 = 2
Answer for Query 4 = 1
Answer for Query 5 = 1
Answer for Query 6 = 3
Time Complexity: O(Q * N)
Auxiliary Space: O(N)
Method 2 (Efficient):
We can solve this problem using the MO's Algorithm.
We assign starting index, ending index and query number to each query, Each query takes the following form-
Starting Index(L): Starting Index of the subarray covered under the query;
Ending Index(R) : Ending Index of the subarray covered under the query;
Query Number(Index) : Since queries are sorted, this tells us original position of the query so that we answer the queries in the original order
Firstly, we divide the queries into blocks and sort the queries using a custom comparator.
Now we process the queries offline where we keep two pointers i.e. MO_RIGHT and MO_LEFT with each incoming query, we move these pointers forward and backward and insert and delete elements according to the starting and ending indices of the current query.
Let the current running answer be current_ans.
Whenever we insert an element we increment the frequency of the included element, if this frequency is equal to the element we just included, we increment the current_ans.If the frequency of this element becomes (current element + 1) this means that earlier this element was counted in the current_ans when it was equal to its frequency, thus we need to decrement current_ans in this case.
Whenever we delete/remove an element we decrement the frequency of the excluded element, if this frequency is equal to the element we just excluded, we increment the current_ans.If the frequency of this element becomes (current element - 1) this means that earlier this element was counted in the current_ans when it was equal to its frequency, thus we need to decrement current_ans in this case.
Implementation:
C++
/* C++ Program to answer Q queries to
find number of times an element x
appears x times in a Query subarray */
#include <bits/stdc++.h>
using namespace std;
// Variable to represent block size.
// This is made global so compare()
// of sort can use it.
int block;
// Structure to represent a query range
struct Query {
int L, R, index;
};
/* 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;
}
/* Inserts element (x) into current range
and updates current answer */
void add(int x, int& currentAns,
unordered_map<int, int>& freq)
{
// increment frequency of this element
freq[x]++;
// if this element was previously
// contributing to the currentAns,
// decrement currentAns
if (freq[x] == (x + 1))
currentAns--;
// if this element has frequency
// equal to its value, increment
// currentAns
else if (freq[x] == x)
currentAns++;
}
/* Removes element (x) from current
range btw L and R and updates
current Answer */
void remove(int x, int& currentAns,
unordered_map<int, int>& freq)
{
// decrement frequency of this element
freq[x]--;
// if this element has frequency equal
// to its value, increment currentAns
if (freq[x] == x)
currentAns++;
// if this element was previously
// contributing to the currentAns
// decrement currentAns
else if (freq[x] == (x - 1))
currentAns--;
}
/* Utility Function to answer all queries
and build the ans array in the original
order of queries */
void queryResultsUtil(int a[], Query q[],
int ans[], int m)
{
// map to store freq of each element
unordered_map<int, int> freq;
// Initialize current L, current R
// and current sum
int currL = 0, currR = 0;
int currentAns = 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;
int index = q[i].index;
// 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
// removed
while (currL < L) {
remove(a[currL], currentAns, freq);
currL++;
}
// Add Elements of current Range
while (currL > L) {
currL--;
add(a[currL], currentAns, freq);
}
while (currR <= R) {
add(a[currR], currentAns, freq);
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 Removed
while (currR > R + 1) {
currR--;
remove(a[currR], currentAns, freq);
}
// Store current ans as the Query ans for
// Query number index
ans[index] = currentAns;
}
}
/* Wrapper for queryResultsUtil() and outputs the
ans array constructed by answering all queries */
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);
int* ans = new int[m];
queryResultsUtil(a, q, ans, m);
for (int i = 0; i < m; i++) {
cout << "Answer for Query " << (i + 1)
<< " = " << ans[i] << endl;
}
}
// Driver program
int main()
{
int A[] = { 1, 2, 2, 3, 3, 3 };
int n = sizeof(A) / sizeof(A[0]);
// 2D array of queries with 2 columns
Query queries[] = { { 0, 1, 0 },
{ 1, 1, 1 },
{ 0, 2, 2 },
{ 1, 3, 3 },
{ 3, 5, 4 },
{ 0, 5, 5 } };
// calculating number of queries
int q = sizeof(queries) / sizeof(queries[0]);
// Print result for each Query
queryResults(A, n, queries, q);
return 0;
}
Java
/* Java Program to answer Q queries to
find number of times an element x
appears x times in a Query subarray */
import java.util.*;
public class GFG {
// Variable to represent block size.
// This is made global so compare()
// of sort can use it.
static int block;
// Structure to represent a query range
static class Query {
int L, R, index;
Query(int L, int R, int index) {
this.L = L;
this.R = R;
this.index = index;
}
}
/* 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. */
static boolean 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;
}
/* Inserts element (x) into current range
and updates current answer */
static void add(int x, int[] currentAns, HashMap<Integer, Integer> freq) {
// increment frequency of this element
freq.put(x, freq.getOrDefault(x, 0) + 1);
// if this element was previously
// contributing to the currentAns,
// decrement currentAns
if (freq.get(x) == (x + 1)) {
currentAns[0]--;
// if this element has frequency
// equal to its value, increment
// currentAns
} else if (freq.get(x) == x) {
currentAns[0]++;
}
}
/* Removes element (x) from current
range btw L and R and updates
current Answer */
static void remove(int x, int[] currentAns, HashMap<Integer, Integer> freq) {
// decrement frequency of this element
freq.put(x, freq.get(x) - 1);
// if this element has frequency equal
// to its value, increment currentAns
if (freq.get(x) == x) {
currentAns[0]++;
// if this element was previously
// contributing to the currentAns
// decrement currentAns
} else if (freq.get(x) == (x - 1)) {
currentAns[0]--;
}
}
/* Utility Function to answer all queries
and build the ans array in the original
order of queries */
static void queryResultsUtil(int[] a, Query[] q, int[] ans, int m) {
// map to store freq of each element
HashMap<Integer, Integer> freq = new HashMap<>();
// Initialize current L, current R
// and current sum
int currL = 0, currR = 0;
int[] currentAns = {0};
// Traverse through all queries
for (int i = 0; i < m; i++) {
int L = q[i].L, R = q[i].R;
int index = q[i].index;
// 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
// removed
while (currL < L) {
remove(a[currL], currentAns, freq);
currL++;
}
// Add Elements of current Range
while (currL > L) {
currL--;
add(a[currL], currentAns, freq);
}
while (currR <= R) {
add(a[currR], currentAns, freq);
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 Removed
while (currR > R + 1) {
currR--;
remove(a[currR], currentAns, freq);
}
// Store current ans as the Query ans for
// Query number index
ans[index] = currentAns[0];
}
}
/* Wrapper for queryResultsUtil() and outputs the
ans array constructed by answering all queries */
static void queryResults(int[] a, int n, Query[] q, int m) {
// Find block size
block = (int) Math.sqrt(n);
Arrays.sort(q, new Comparator<Query>() {
@Override
public int compare(Query x, Query y) {
// Different blocks, sort by block.
if (x.L / block != y.L / block)
return Integer.compare(x.L / block, y.L / block);
// Same block, sort by R value
return Integer.compare(x.R, y.R);
}
});
int[] ans = new int[m];
queryResultsUtil(a, q, ans, m);
for (int i = 0; i < m; i++) {
System.out.println("Answer for Query " + (i + 1) + " = " + ans[i]);
}
}
public static void main(String[] args) {
int[] A = {1, 2, 2, 3, 3, 3};
int n = A.length;
// 2D array of queries with 2 columns
Query[] queries = {
new Query(0, 1, 0),
new Query(1, 1, 1),
new Query(0, 2, 2),
new Query(1, 3, 3),
new Query(3, 5, 4),
new Query(0, 5, 5)
};
// calculating number of queries
int q = queries.length;
// Print result for each Query
queryResults(A, n, queries, q);
}
}
//this code is contributed by bhardwajji
Python3
# /* python Program to answer Q queries to
# find number of times an element x
# appears x times in a Query subarray */
from functools import cmp_to_key
import math
# Variable to represent block size.
# This is made global so compare()
# of sort can use it.
block = 0
# Structure to represent a query range
class Query:
def __init__(self, L, R, index):
self.L = L
self.R = R
self.index = index
# /* 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. */
def Compare(x, y):
# Different blocks, sort by block.
if (block != 0 and x.L / block != y.L / block):
return x.L / block - y.L / block
# Same block, sort by R value
return x.R- y.R
# /* Inserts element (x) into current range
# and updates current answer */
def add(x, currentAns, freq):
# increment frequency of this element
if(x in freq):
freq[x] = freq[x] + 1
else:
freq[x] = 1
# if this element was previously
# contributing to the currentAns,
# decrement currentAns
if (freq[x] == (x + 1)):
currentAns[0] = currentAns[0] - 1
# if this element has frequency
# equal to its value, increment
# currentAns
elif(freq[x] == x):
currentAns[0] = currentAns[0] + 1
# /* Removes element (x) from current
# range btw L and R and updates
# current Answer */
def remove(x, currentAns, freq):
# decrement frequency of this element
freq[x] = freq[x] - 1;
# if this element has frequency equal
# to its value, increment currentAns
if (freq[x] == x):
currentAns[0] = currentAns[0] + 1
# if this element was previously
# contributing to the currentAns
# decrement currentAns
elif(freq[x] == (x-1)):
currentAns[0] = currentAns[0] - 1
# /* Utility Function to answer all queries
# and build the ans array in the original
# order of queries */
def queryResultsUtil(a, q, ans, m):
# map to store freq of each element
freq = {}
# Initialize current L, current R
# and current sum
currL = 0
currR = 0
currentAns = [0]
# Traverse through all queries
for i in range(m):
L = q[i].L
R = q[i].R
index = q[i].index
# 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
# removed
while (currL < L):
remove(a[currL], currentAns, freq)
currL = currL + 1
# Add Elements of current Range
while (currL > L):
currL = currL - 1
add(a[currL], currentAns, freq)
while (currR <= R):
add(a[currR], currentAns, freq)
currR = currR + 1
# 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 Removed
while (currR > R + 1):
currR = currR - 1
remove(a[currR], currentAns, freq)
# Store current ans as the Query ans for
# Query number index
ans[index] = currentAns[0]
# /* Wrapper for queryResultsUtil() and outputs the
# ans array constructed by answering all queries */
def queryResults(a, n, q, m):
# Find block size
block = math.floor(math.sqrt(n))
sorted(q, key=cmp_to_key(Compare))
ans = [0]*m
queryResultsUtil(a, q, ans, m)
for i in range(m):
print("Answer for Query " ,(i + 1) ," = " ,ans[i])
A = [1, 2, 2, 3, 3, 3]
n = len(A)
# 2D array of queries with 2 columns
queries = [
Query(0, 1, 0),
Query(1, 1, 1),
Query(0, 2, 2),
Query(1, 3, 3),
Query(3, 5, 4),
Query(0, 5, 5)
]
# calculating number of queries
q = len(queries)
# Print result for each Query
queryResults(A, n, queries, q)
# this code is contributed by Arushi Jindal.
JavaScript
/* Javascript Program to answer Q queries to
find number of times an element x
appears x times in a Query subarray */
// Variable to represent block size.
// This is made global so compare()
// of sort can use it.
let block = 0;
// Structure to represent a query range
class Query {
constructor(L, R, index) {
this.L = L;
this.R = R;
this.index = index;
}
}
/* 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. */
function Compare(x, 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;
}
/* Inserts element (x) into current range
and updates current answer */
function add(x, currentAns, freq) {
// increment frequency of this element
if(x in freq){
freq[x] = freq[x] + 1;
}
else{
freq[x] = 1;
}
// if this element was previously
// contributing to the currentAns,
// decrement currentAns
if (freq[x] == (x + 1)) {
currentAns[0]--;
// if this element has frequency
// equal to its value, increment
// currentAns
} else if (freq[x] == x) {
currentAns[0]++;
}
}
/* Removes element (x) from current
range btw L and R and updates
current Answer */
function remove(x, currentAns, freq) {
// decrement frequency of this element
freq[x] = freq[x] - 1;
// if this element has frequency equal
// to its value, increment currentAns
if (freq[x] == x) {
currentAns[0]++;
// if this element was previously
// contributing to the currentAns
// decrement currentAns
} else if (freq[x] == (x - 1)) {
currentAns[0]--;
}
}
/* Utility Function to answer all queries
and build the ans array in the original
order of queries */
function queryResultsUtil(a, q, ans, m) {
// map to store freq of each element
let freq = {}
// Initialize current L, current R
// and current sum
let currL = 0, currR = 0;
let currentAns = [0];
// Traverse through all queries
for (let i = 0; i < m; i++) {
let L = q[i].L, R = q[i].R;
let index = q[i].index;
// 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
// removed
while (currL < L) {
remove(a[currL], currentAns, freq);
currL++;
}
// Add Elements of current Range
while (currL > L) {
currL--;
add(a[currL], currentAns, freq);
}
while (currR <= R) {
add(a[currR], currentAns, freq);
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 Removed
while (currR > R + 1) {
currR--;
remove(a[currR], currentAns, freq);
}
// Store current ans as the Query ans for
// Query number index
ans[index] = currentAns[0];
}
}
/* Wrapper for queryResultsUtil() and outputs the
ans array constructed by answering all queries */
function queryResults(a, n, q, m) {
// Find block size
block = Math.floor(Math.sqrt(n));
q.sort(Compare);
let ans = new Array(m);
queryResultsUtil(a, q, ans, m);
for (let i = 0; i < m; i++) {
console.log("Answer for Query " + (i + 1) + " = " + ans[i]);
}
}
let A = [1, 2, 2, 3, 3, 3];
let n = A.length;
// 2D array of queries with 2 columns
let queries = [
new Query(0, 1, 0),
new Query(1, 1, 1),
new Query(0, 2, 2),
new Query(1, 3, 3),
new Query(3, 5, 4),
new Query(0, 5, 5)
];
// calculating number of queries
let q = queries.length;
// Print result for each Query
queryResults(A, n, queries, q);
//this code is contributed by Arushi Jindal.
C#
/* C# Program to answer Q queries to
find number of times an element x
appears x times in a Query subarray */
using System;
using System.Collections.Generic;
public class GFG {
// Variable to represent block size.
// This is made global so compare()
// of sort can use it.
static int block;
/* Inserts element (x) into current range
and updates current answer *//* Removes element (x) from current
range btw L and R and updates
current Answer */
static void add(int x, int[] currentAns,
Dictionary<int, int> freq)
{
freq.TryGetValue(x, out int value);
freq[x] = value + 1;
if (freq[x] == x + 1) {
currentAns[0]--;
}
else if (freq[x] == x) {
currentAns[0]++;
}
}
/* Removes element (x) from current
range btw L and R and updates
current Answer */
static void remove(int x, int[] currentAns,
Dictionary<int, int> freq)
{
freq[x]--;
if (freq[x] == x) {
currentAns[0]++;
}
else if (freq[x] == x - 1) {
currentAns[0]--;
}
}
// Structure to represent a query range
class Query {
public int L;
public int R;
public int index;
public Query(int L, int R, int index)
{
this.L = L;
this.R = R;
this.index = index;
}
}
/* Utility Function to answer all queries
and build the ans array in the original
order of queries */
static void queryResultsUtil(int[] a, Query[] q,
int[] ans, int m)
{
// map to store freq of each element
var freq = new Dictionary<int, int>();
// Initialize current L, current R
// and current sum
int currL = 0, currR = 0;
int[] currentAns = { 0 };
// Traverse through all queries
for (int i = 0; i < m; i++) {
int L = q[i].L, R = q[i].R;
int index = q[i].index;
// 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
// removed
while (currL < L) {
remove(a[currL], currentAns, freq);
currL++;
}
// Add Elements of current Range
while (currL > L) {
currL--;
add(a[currL], currentAns, freq);
}
while (currR <= R) {
add(a[currR], currentAns, freq);
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 Removed
while (currR > R + 1) {
currR--;
remove(a[currR], currentAns, freq);
}
ans[index] = currentAns[0];
}
}
/* Wrapper for queryResultsUtil() and outputs the
ans array constructed by answering all queries */
static void queryResults(int[] a, int n, Query[] q,
int m)
{
block = (int)Math.Sqrt(n);
Array.Sort(q, (x, y) => {
/* 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. */
if (x.L / block != y.L / block) {
return x.L / block - y.L / block;
}
return x.R - y.R;
});
int[] ans = new int[m];
queryResultsUtil(a, q, ans, m);
for (int i = 0; i < m; i++) {
Console.WriteLine("Answer for Query " + (i + 1)
+ " = " + ans[i]);
}
}
public static void Main(string[] args)
{
int[] A = { 1, 2, 2, 3, 3, 3 };
int n = A.Length;
Query[] q
= { new Query(0, 1, 0), new Query(1, 1, 1),
new Query(0, 2, 2), new Query(1, 3, 3),
new Query(3, 5, 4), new Query(0, 5, 5) };
int m = q.Length;
queryResults(A, n, q, m);
}
}
OutputAnswer for Query 1 = 1
Answer for Query 2 = 0
Answer for Query 3 = 2
Answer for Query 4 = 1
Answer for Query 5 = 1
Answer for Query 6 = 3
Time Complexity of this approach using MO's Algorithm is O(Q * sqrt(N) * logA) where logA is the complexity to insert an element A into the unordered_map for each query.
Auxiliary Space: O(N+Q)
Similar Reads
Range Queries for Frequencies of array elements
Given an array of n non-negative integers. The task is to find frequency of a particular element in the arbitrary range of array[]. The range is given as positions (not 0 based indexes) in array. There can be multiple queries of given type. Examples: Input : arr[] = {2, 8, 6, 9, 8, 6, 8, 2, 11}; lef
13 min read
Queries for count of array elements with values in given range with updates
Given an array arr[] of size N and a matrix Q consisting of queries of the following two types:Â 1 L R : Print the number of elements lying in the range [L, R].2 i x : Set arr[i] = x Examples:Â Input: arr[] = {1, 2, 2, 3, 4, 4, 5, 6}, Q = {{1, {3, 5}}, {1, {2, 4}}, {1, {1, 2}}, {2, {1, 7}}, {1, {1,
15+ min read
Find array elements with frequencies in range [l , r]
Given an array of integers, find the elements from the array whose frequency lies in the range [l, r]. Examples: Input : arr[] = { 1, 2, 3, 3, 2, 2, 5 } l = 2, r = 3 Output : 2 3 3 2 2 Approach : Take a hash map, which will store the frequency of all the elements in the array.Now, traverse once agai
9 min read
Elements of first array that have more frequencies
Given two arrays (which may or may not be sorted). These arrays are such that they might have some common elements in them. We need to find elements whose counts of occurrences are more in first array than second. Examples: Input : ar1[] = {1, 2, 2, 2, 3, 3, 4, 5} ar2[] = {2, 2, 3, 3, 3, 4} Output :
7 min read
Queries for number of array elements in a range with Kth Bit Set
Given an array of N positive (32-bit)integers, the task is to answer Q queries of the following form: Query(L, R, K): Print the number of elements of the array in the range L to R, which have their Kth bit as set Note: Consider LSB to be indexed at 1. Examples: Input : arr[] = { 8, 9, 1, 3 } Query 1
15+ min read
Print all Repetitive elements in given Array within value range [A, B] for Q queries
Given an array arr[] of size N, and Q queries of the form [A, B], the task is to find all the unique elements from the array which are repetitive and their values lie between A and B (both inclusive) for each of the Q queries. Examples: Input: arr[] = { 1, 5, 1, 2, 3, 3, 4, 0, 0 }, Q = 2, queries={
13 min read
Array range queries for searching an element
Given an array of N elements and Q queries of the form L R X. For each query, you have to output if the element X exists in the array between the indices L and R(included). Prerequisite : Mo's Algorithms Examples : Input : N = 5 arr = [1, 1, 5, 4, 5] Q = 3 1 3 2 2 5 1 3 5 5 Output : No Yes Yes Expla
15+ min read
Find element with highest frequency in given nested Array
Given an array arr[] of N integers. The task is to create a frequency array freq[] of the given array arr[] and find the maximum element of the frequency array. If two elements have the same frequency in the array freq[], then return the element which has a smaller value. Examples: Input: arr[] = {1
8 min read
Queries for elements having values within the range A to B using MO's Algorithm
Prerequisites: MO's algorithm, SQRT DecompositionGiven an array arr[] of N elements and two integers A to B, the task is to answer Q queries each having two integers L and R. For each query, find the number of elements in the subarray arr[L, R] which lies within the range A to B (inclusive). Example
15+ min read
Largest subarray with frequency of all elements same
Given an array arr[] of N integers, the task is to find the size of the largest subarray with frequency of all elements the same. Examples: Input: arr[] = {1, 2, 2, 5, 6, 5, 6} Output: 6 Explanation: The subarray = {2, 2, 5, 6, 5, 6} has frequency of every element is 2. Input: arr[] = {1, 1, 1, 1, 1
15+ min read