// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
int BLOCK_SIZE;
// Structure to represent a query range
// and its index
struct query {
int l, r, idx;
};
// Custom comparator
bool comparator(query a, query b)
{
if ((a.l / BLOCK_SIZE) != (b.l / BLOCK_SIZE))
return (a.l / BLOCK_SIZE) < (b.l / BLOCK_SIZE);
return ((a.l / BLOCK_SIZE) & 1) ? (a.r < b.r)
: (a.r > b.r);
}
// Function to add elements to the current range
void expand(int idx, int* arr, map<int, int>& numFreq,
set<pair<int, int> >& freqNum)
{
// Remove current element from the set
freqNum.erase({ numFreq[arr[idx]], arr[idx] });
// Increment current element count in the
// map
++numFreq[arr[idx]];
// Insert current element into the set
freqNum.insert({ numFreq[arr[idx]], arr[idx] });
}
// Function to remove elements from the current range
void shrink(int idx, int* arr, map<int, int>& numFreq,
set<pair<int, int> >& freqNum)
{
// Remove current element from the set
freqNum.erase({ numFreq[arr[idx]], arr[idx] });
// Decrement current element count in the
// map
--numFreq[arr[idx]];
// Insert current element into the set
freqNum.insert({ numFreq[arr[idx]], arr[idx] });
}
// Function for Mo's algorithm
pair<int, int>
sqrtDecomposition(int& L, int& R, int l, int r, int* arr,
set<pair<int, int> >& freqNum,
map<int, int>& numFreq)
{
// Iterate until L is greater than l
while (L > l) {
--L;
expand(L, arr, numFreq, freqNum);
}
// Iterate until R is less than r
while (R < r) {
++R;
expand(R, arr, numFreq, freqNum);
}
// Iterate until L is less than l
while (L < l) {
shrink(L, arr, numFreq, freqNum);
++L;
}
// Iterate until R is greater than r
while (R > r) {
shrink(R, arr, numFreq, freqNum);
--R;
}
// Stores the answer for current query
pair<int, int> last = *prev(freqNum.end());
// Return the answer
return last;
}
// Function to find the element having maximum
// frequency and its frequency for all the queries
void getMaxOccuringElement(int arr[], int N, int M,
pair<int, int> Q[])
{
// Compute each block size
BLOCK_SIZE = (int)sqrt(N + .0) + 1;
// Stores the queries
query queries[M];
for (int i = 0; i < M; ++i) {
queries[i].l = Q[i].first;
queries[i].r = Q[i].second;
queries[i].idx = i;
}
// Sort all the queries
sort(queries, queries + M, comparator);
// Initiali ranges of Mos
int L = 0, R = -1;
// Stores the answer
pair<int, int> ans[M];
set<pair<int, int> > freqNum;
map<int, int> numFreq;
// Traverse the query array
for (int i = 0; i < M; ++i) {
int l = queries[i].l;
int r = queries[i].r;
// Stores the answer for current
// query
ans[queries[i].idx] = sqrtDecomposition(
L, R, l, r, arr, freqNum, numFreq);
}
// Print the answer
for (int i = 0; i < M; ++i) {
cout << ans[i].second << " Occurs " << ans[i].first
<< " times" << endl;
}
}
// Driver Code
int main()
{
int arr[] = { 5, 7, 5, 5, 2, 7, 3, 2, 5, 2 };
pair<int, int> Q[]
= { { 0, 9 }, { 3, 6 }, { 4, 8 }, { 1, 5 } };
int N = sizeof(arr) / sizeof(arr[0]);
int M = sizeof(Q) / sizeof(Q[0]);
getMaxOccuringElement(arr, N, M, Q);
return 0;
}