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