Related Articles
Queries for count of even digit sum elements in given range using MO’s Algorithm
• Last Updated : 19 Nov, 2020

Given an array arr[] of N elements, the task is to answer Q queries each having two integers L and R. For each query, the task is to find the number of elements in the subarray arr[L…R] whose digit sum is even.

Examples:

Input:arr[] = {7, 3, 19, 13, 5, 4}
query = { {1, 5}, {0, 1} }
Output:
Explanation:
Query 1: Elements 19, 13 and 4 have even digit sum in the subarray: {3, 9, 13, 5, 4}.
Query 2: No elements have even sum in the subarray: {7, 3}

Input:arr[] = {0, 1, 2, 3, 4, 5, 6, 7}
query = { 3, 5 }
Output:

We have already discussed this approach: Queries for the count of even digit sum elements in the given range using Segment Tree

Approach: (Using MO’s Algorithm)
The idea is to pre-process all queries so that result of one query can be used in the next query.

1. Sort all queries in a way that queries with L values from 0 to √n – 1 are put together, followed by queries from √n to 2×√n – 1, and so on. All queries within a block are sorted in increasing order of R values.
2. Process all queries one by one and increase the count of even digit sum elements and store the result in the structure.
• Let count_even store the count of even digits sum elements in the previous query.
• Remove extra elements of previous query and add new elements for the current query. For example, if previous query was [0, 8] and the current query is [3, 9], then remove the elements arr, arr and arr and add arr.
3. In order to display the results, sort the queries in the order they were provided.

Helper functions:

• If the current element has even digit sum then increase the count of count_even.

Removing elements()

• If the current element has even digit sum then decrease the count of count_even.

Below code is the implementation of the above approach:

## C++

 `// C++ program to count of even` `// digit sum elements in the given` `// range using MO's algorithm`   `#include ` `using` `namespace` `std;`   `#define MAX 100000`   `// 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 {`   `    ``// Starting index` `    ``int` `L;`   `    ``// Ending index` `    ``int` `R;`   `    ``// Index of query` `    ``int` `index;`   `    ``// Count of even` `    ``// even digit sum` `    ``int` `even;` `};`   `// To store the count of` `// even digit sum` `int` `count_even;`   `// 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)` `{` `    ``// 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;` `}`   `// Function used to sort all queries` `// in order of their index value so that` `// results of queries can be printed` `// in same order as of input` `bool` `compare1(Query x, Query y)` `{` `    ``return` `x.index < y.index;` `}`   `// Function to find the digit sum` `// for a number` `int` `digitSum(``int` `num)` `{` `    ``int` `sum = 0;` `    ``while` `(num) {` `        ``sum += (num % 10);` `        ``num /= 10;` `    ``}`   `    ``return` `sum;` `}`   `// Function to Add elements` `// of current range` `void` `add(``int` `currL, ``int` `a[])` `{` `    ``// If digit sum of a[currL]` `    ``// is even then increment` `    ``if` `(digitSum(a[currL]) % 2 == 0)` `        ``count_even++;` `}`   `// Function to remove elements` `// of previous range` `void` `remove``(``int` `currR, ``int` `a[])` `{`   `    ``// If digit sum of a[currL]` `    ``// is even then decrement` `    ``if` `(digitSum(a[currR]) % 2 == 0)` `        ``count_even--;` `}`   `// Function to generate` `// the result of queries` `void` `queryResults(``int` `a[], ``int` `n,` `                  ``Query q[], ``int` `m)` `{`   `    ``// Initialize number of` `    ``// even digit sum to 0` `    ``count_even = 0;`   `    ``// Find block size` `    ``block = (``int``)``sqrt``(n);`   `    ``// 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 current range` `        ``int` `L = q[i].L, R = q[i].R;`   `        ``// 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++;` `        ``}`   `        ``q[i].even = count_even;` `    ``}` `}` `// Function to display the results of` `// queries in their initial order` `void` `printResults(Query q[], ``int` `m)` `{` `    ``sort(q, q + m, compare1);` `    ``for` `(``int` `i = 0; i < m; i++) {` `        ``cout << q[i].even << endl;` `    ``}` `}`   `// Driver Code` `int` `main()` `{`   `    ``int` `arr[] = { 5, 2, 3, 1, 4, 8, 10, 12 };` `    ``int` `n = ``sizeof``(arr) / ``sizeof``(arr);`   `    ``Query q[] = { { 1, 3, 0, 0 },` `                  ``{ 0, 4, 1, 0 },` `                  ``{ 4, 7, 2, 0 } };`   `    ``int` `m = ``sizeof``(q) / ``sizeof``(q);`   `    ``queryResults(arr, n, q, m);`   `    ``printResults(q, m);`   `    ``return` `0;` `}`

## Java

 `// Java program to count of even` `// digit sum elements in the given` `// range using MO's algorithm` `import` `java.util.Arrays;` `import` `java.util.Collections;` `import` `java.util.Comparator;`   `class` `GFG{`   `static` `int` `MAX = ``100000``;`   `// 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 ` `{` `    `  `    ``// Starting index` `    ``int` `L;`   `    ``// Ending index` `    ``int` `R;`   `    ``// Index of query` `    ``int` `index;`   `    ``// Count of even` `    ``// even digit sum` `    ``int` `even;`   `    ``public` `Query(``int` `l, ``int` `r, ` `                 ``int` `index, ``int` `even) ` `    ``{` `        ``this``.L = l;` `        ``this``.R = r;` `        ``this``.index = index;` `        ``this``.even = even;` `    ``}` `};`   `// To store the count of` `// even digit sum` `static` `int` `count_even;`   `// Function to find the digit sum` `// for a number` `static` `int` `digitSum(``int` `num) ` `{` `    ``int` `sum = ``0``;` `    ``while` `(num > ``0``) ` `    ``{` `        ``sum += (num % ``10``);` `        ``num /= ``10``;` `    ``}` `    ``return` `sum;` `}`   `// Function to Add elements` `// of current range` `static` `void` `add(``int` `currL, ``int` `a[])` `{` `    `  `    ``// If digit sum of a[currL]` `    ``// is even then increment` `    ``if` `(digitSum(a[currL]) % ``2` `== ``0``)` `        ``count_even++;` `}`   `// Function to remove elements` `// of previous range` `static` `void` `remove(``int` `currR, ``int` `a[]) ` `{` `    `  `    ``// If digit sum of a[currL]` `    ``// is even then decrement` `    ``if` `(digitSum(a[currR]) % ``2` `== ``0``)` `        ``count_even--;` `}`   `// Function to generate` `// the result of queries` `static` `void` `queryResults(``int` `a[], ``int` `n, ` `                       ``Query q[], ``int` `m)` `{` `    `  `    ``// Initialize number of` `    ``// even digit sum to 0` `    ``count_even = ``0``;`   `    ``// Find block size` `    ``block = (``int``) Math.sqrt(n);`   `    ``// Sort all queries so that queries of` `    ``// same blocks are arranged together.` `    ``Collections.sort(Arrays.asList(q), ` `                     ``new` `Comparator()` `    ``{` `        `  `        ``// 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.` `        ``public` `int` `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;` `        ``}` `    ``});`   `    ``// 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 current range` `        ``int` `L = q[i].L, R = q[i].R;`   `        ``// 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++;` `        ``}` `        ``q[i].even = count_even;` `    ``}` `}`   `// Function to display the results of` `// queries in their initial order` `static` `void` `printResults(Query q[], ``int` `m) ` `{` `    ``Collections.sort(Arrays.asList(q), ` `             ``new` `Comparator()` `    ``{` `        `  `        ``// Function used to sort all queries` `        ``// in order of their index value so that` `        ``// results of queries can be printed` `        ``// in same order as of input` `        ``public` `int` `compare(Query x, Query y) ` `        ``{` `            ``return` `x.index - y.index;` `        ``}` `    ``});` `    ``for``(``int` `i = ``0``; i < m; i++)` `    ``{` `        ``System.out.println(q[i].even);` `    ``}` `}`   `// Driver Code` `public` `static` `void` `main(String[] args)` `{` `    ``int` `arr[] = { ``5``, ``2``, ``3``, ``1``, ``4``, ``8``, ``10``, ``12` `};` `    ``int` `n = arr.length;`   `    ``Query q[] = { ``new` `Query(``1``, ``3``, ``0``, ``0``), ` `                  ``new` `Query(``0``, ``4``, ``1``, ``0``), ` `                  ``new` `Query(``4``, ``7``, ``2``, ``0``) };`   `    ``int` `m = q.length;`   `    ``queryResults(arr, n, q, m);`   `    ``printResults(q, m);` `}` `}`   `// This code is contributed by sanjeev2552`

Output:

```1
2
2

```

Time Complexity: O(Q x √N) My Personal Notes arrow_drop_up
Recommended Articles
Page :