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=5

Initially 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; ` `} ` |

*chevron_right*

*filter_none*

**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.