Given an array **arr** of size **N** and **Q **queries of the form L, R and X, the task is to print the number of elements less than or equal to X in the subarray represented by L to R.

**Prerequisites:** MO’s Algorithm, Sqrt Decomposition

**Examples:**

Input:arr[] = {2, 3, 4, 5} Q = {{0, 3, 5}, {0, 2, 2}}Output:4 1Explanation:Number of elements less than or equal to 5 in arr[0..3] is 4 (all elements) Number of elements less than or equal to 2 in arr[0..2] is 1 (only 2)

**Approach:**

The idea of MO’s algorithm is to pre-process all queries so that result of one query can be used in the next query.

Let **arr[0…n-1]** be input array and **Q[0..m-1]** be an array of queries.

- Sort all queries in a way that queries with L values from
**0 to √n – 1**are put together, then all queries from**√n to 2×√n – 1**, and so on. All queries within a block are sorted in increasing order of R values. - Process all queries one by one in a way that every query uses result computed in the previous query.
- We will maintain the
**frequency array**that will count the frequency of arr[i] as they appear in the range [L, R]. **For example:**arr[]=[3, 4, 6, 2, 7, 1], L=0, R=4 and X=5Initially frequency array is initialized to 0 i.e freq[]=[0….0]

**Step 1**– add arr[0] and increment its frequency as freq[arr[0]]++ i.e freq[3]++

and freq[]=[0, 0, 0, 1, 0, 0, 0, 0]**Step 2**– Add arr[1] and increment freq[arr[1]]++ i.e freq[4]++

and freq[]=[0, 0, 0, 1, 1, 0, 0, 0]**Step 3**– Add arr[2] and increment freq[arr[2]]++ i.e freq[6]++

and freq[]=[0, 0, 0, 1, 1, 0, 1, 0]**Step 4**– Add arr[3] and increment freq[arr[3]]++ i.e freq[2]++

and freq[]=[0, 0, 1, 1, 1, 0, 1, 0]**Step 5**– Add arr[4] and increment freq[arr[4]]++ i.e freq[7]++

and freq[]=[0, 0, 1, 1, 1, 0, 1, 1]**Step 6**– Now we need to find the numbers of elements less than or equal to X(here X=5).**Step 7**– The answer is equal toTo calculate the

**sum in step 7**, we cannot do iteration because that would lead to O(N) time complexity per query so we will use**sqrt decomposition technique**to find the sum whose**time complexity is O(√n) per query**.

`// C++ program to answer queries to ` `// count number of elements smaller ` `// than or equal to x.` `#include <bits/stdc++.h>` `using` `namespace` `std;` ` ` `#define MAX 100001` `#define SQRSIZE 400` ` ` `// Variable to represent block size.` `// This is made global so compare()` `// of sort can use it.` `int` `query_blk_sz;` ` ` `// Structure to represent a` `// query range` `struct` `Query {` ` ` ` ` `int` `L;` ` ` `int` `R;` ` ` `int` `x;` `};` ` ` `// Frequency array` `// to keep count of elements` `int` `frequency[MAX];` ` ` `// Array which contains the frequency` `// of a particular block` `int` `blocks[SQRSIZE];` ` ` `// Block size` `int` `blk_sz;` ` ` `// Function used to sort all queries ` `// so that all queries of the same` `// block are arranged together and ` `// within a block, queries are sorted ` `// in increasing order of R values.` `bool` `compare(Query x, Query y)` `{` ` ` `if` `(x.L / query_blk_sz != ` ` ` `y.L / query_blk_sz)` ` ` `return` `x.L / query_blk_sz < ` ` ` `y.L / query_blk_sz;` ` ` ` ` `return` `x.R < y.R;` `}` ` ` `// Function used to get the block` `// number of current a[i] i.e ind` `int` `getblocknumber(` `int` `ind)` `{` ` ` `return` `(ind) / blk_sz;` `}` ` ` `// Function to get the answer` `// of range [0, k] which uses the` `// sqrt decompostion technique` `int` `getans(` `int` `k)` `{` ` ` `int` `ans = 0;` ` ` `int` `left_blk, right_blk;` ` ` `left_blk = 0;` ` ` `right_blk = getblocknumber(k);` ` ` ` ` `// If left block is equal to` ` ` `// rigth block then we can traverse` ` ` `// that block` ` ` `if` `(left_blk == right_blk) {` ` ` `for` `(` `int` `i = 0; i <= k; i++)` ` ` `ans += frequency[i];` ` ` `}` ` ` `else` `{` ` ` `// Traversing first block in ` ` ` `// range` ` ` `for` `(` `int` `i = 0; i < ` ` ` `(left_blk + 1) * blk_sz; i++)` ` ` `ans += frequency[i];` ` ` ` ` `// Traversing completely overlapped` ` ` `// blocks in range` ` ` `for` `(` `int` `i = left_blk + 1; ` ` ` `i < right_blk; i++)` ` ` `ans += blocks[i];` ` ` ` ` `// Traversing last block in range` ` ` `for` `(` `int` `i = right_blk * blk_sz;` ` ` `i <= k; i++)` ` ` `ans += frequency[i];` ` ` `}` ` ` `return` `ans;` `}` ` ` `void` `add(` `int` `ind, ` `int` `a[])` `{` ` ` `// Increment the frequency of a[ind]` ` ` `// in the frequency array` ` ` `frequency[a[ind]]++;` ` ` ` ` `// Get the block number of a[ind]` ` ` `// to update the result in blocks` ` ` `int` `block_num = getblocknumber(a[ind]);` ` ` ` ` `blocks[block_num]++;` `}` `void` `remove` `(` `int` `ind, ` `int` `a[])` `{` ` ` `// Decrement the frequency of ` ` ` `// a[ind] in the frequency array` ` ` `frequency[a[ind]]--;` ` ` ` ` `// Get the block number of a[ind]` ` ` `// to update the result in blocks` ` ` `int` `block_num = getblocknumber(a[ind]);` ` ` ` ` `blocks[block_num]--;` `}` `void` `queryResults(` `int` `a[], ` `int` `n,` ` ` `Query q[], ` `int` `m)` `{` ` ` ` ` `// Initialize the block size` ` ` `// for queries` ` ` `query_blk_sz = ` `sqrt` `(m);` ` ` ` ` `// Sort all queries so that queries` ` ` `// of same blocks are arranged` ` ` `// together.` ` ` `sort(q, q + m, compare);` ` ` ` ` `// Initialize current L,` ` ` `// current R and current result` ` ` `int` `currL = 0, currR = 0;` ` ` ` ` `for` `(` `int` `i = 0; i < m; i++) {` ` ` ` ` `// L and R values of the ` ` ` `// current range` ` ` ` ` `int` `L = q[i].L, R = q[i].R,` ` ` `x = q[i].x;` ` ` ` ` `// Add Elements of current` ` ` `// range` ` ` `while` `(currR <= R) {` ` ` `add(currR, a);` ` ` `currR++;` ` ` `}` ` ` `while` `(currL > L) {` ` ` `add(currL - 1, a);` ` ` `currL--;` ` ` `}` ` ` ` ` `// Remove element of previous` ` ` `// range` ` ` `while` `(currR > R + 1)` ` ` ` ` `{` ` ` `remove` `(currR - 1, a);` ` ` `currR--;` ` ` `}` ` ` `while` `(currL < L) {` ` ` `remove` `(currL, a);` ` ` `currL++;` ` ` `}` ` ` `printf` `(` `"query[%d, %d, %d] : %d\n"` `, ` ` ` `L, R, x, getans(x));` ` ` `}` `}` `// Driver code` `int` `main()` `{` ` ` ` ` `int` `arr[] = { 2, 0, 3, 1, 4, 2, 5, 11 };` ` ` `int` `N = ` `sizeof` `(arr) / ` `sizeof` `(arr[0]);` ` ` ` ` `blk_sz = ` `sqrt` `(N);` ` ` `Query Q[] = { { 0, 2, 2 }, { 0, 3, 5 },` ` ` `{ 5, 7, 10 } };` ` ` ` ` `int` `M = ` `sizeof` `(Q) / ` `sizeof` `(Q[0]);` ` ` ` ` `// Answer the queries` ` ` `queryResults(arr, N, Q, M);` ` ` `return` `0;` `}` |

**Output:**

query[0, 2, 2] : 2 query[0, 3, 5] : 4 query[5, 7, 10] : 2

**Time Complexity:** **O(Q × √N)**.

It takes O(Q × √N) time for MO’s algorithm and O(Q × √N) time for sqrt decomposition technique to answer the sum of freq[0]+….freq[k], therefore total time complexity is O(Q × √N + Q × √N) which is O(Q × √N).

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the **DSA Self Paced Course** at a student-friendly price and become industry ready. To complete your preparation from learning a language to DS Algo and many more, please refer **Complete Interview Preparation Course****.**

In case you wish to attend live classes with industry experts, please refer **Geeks Classes Live**