# Queries for count of even digit sum elements in given range using MO’s Algorithm

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[0], arr[1] and arr[2] and add arr[9].
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[0]);` `    ``Query q[] = { { 1, 3, 0, 0 },``                  ``{ 0, 4, 1, 0 },``                  ``{ 4, 7, 2, 0 } };` `    ``int` `m = ``sizeof``(q) / ``sizeof``(q[0]);` `    ``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`

## Python3

 `# Python program to count of even``# digit sum elements in the given``# range using MO's algorithm``import` `math``import` `functools` `MAX` `=` `100000` `arr ``=` `[``5``, ``2``, ``3``, ``1``, ``4``, ``8``, ``10``, ``12``]``n ``=` `len``(arr)` `# Variable to represent block size.``# This is made here so compare()``# of sort can use it.``block ``=` `int``(math.sqrt(n))` `# Class to represent a query range`  `class` `Query:``    ``def` `__init__(``self``, l, r, index, even):``        ``self``.L ``=` `l  ``# Starting index``        ``self``.R ``=` `r  ``# Ending index``        ``self``.index ``=` `index  ``# Index of query``        ``self``.even ``=` `even  ``# Count of even digit sum` `# 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.``def` `compare(x, y):``  ` `    ``# Different blocks, sort by block.``    ``if` `x.L ``/` `block !``=` `y.L ``/` `block:``        ``return` `x.L ``/` `block < y.L ``/` `block``    ``else``:``        ``# Same block, sort by R value``        ``return` `x.R < y.R` `# Function to find the digit sum``# for a number``def` `digitSum(num):``    ``sum` `=` `0``    ``while` `num > ``0``:``        ``sum` `+``=` `(num ``%` `10``)``        ``num ``/``/``=` `10``    ``return` `sum` `# Function to Add elements``# of current range``def` `add(currL, a, count_even):``  ` `    ``# If digit sum of a[currL]``    ``# is even then increment``    ``if` `digitSum(a[currL]) ``%` `2` `=``=` `0``:``        ``count_even ``+``=` `1` `    ``return` `count_even` `# Function to remove elements``# of previous range``def` `remove(currR, a, count_even):``    ``# If digit sum of a[currL]``    ``# is even then decrement``    ``if` `digitSum(a[currR]) ``%` `2` `=``=` `0``:``        ``count_even ``-``=` `1``    ``return` `count_even` `# Function to generate``# the result of queries``def` `queryResults(a, n, q, 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.``    ``q.sort(key``=``functools.cmp_to_key(compare))` `    ``# Initialize current L, current R and``    ``# current result``    ``currL ``=` `0``    ``currR ``=` `0` `    ``for` `i ``in` `range``(m):``        ``# L and R values of current range``        ``L ``=` `q[i].L``        ``R ``=` `q[i].R` `        ``# Add Elements of current range``        ``while` `currR <``=` `R:``            ``count_even ``=` `add(currR, a, count_even)``            ``currR ``+``=` `1` `        ``while` `currL > L:``            ``count_even ``=` `add(currL ``-` `1``, a, count_even)``            ``currL ``-``=` `1` `        ``# Remove element of previous range``        ``while` `currR > R ``+` `1``:``            ``count_even ``=` `remove(currR ``-` `1``, a, count_even)``            ``currR ``-``=` `1` `        ``while` `currL < L:``            ``count_even ``=` `remove(currL, a, count_even)``            ``currL ``+``=` `1` `        ``q[i].even ``=` `count_even` `# Function to display the results of``# queries in their initial order``def` `printResults(q, m):``    ``q.sort(key``=``lambda` `x: x.index)``    ``for` `i ``in` `range``(m):``        ``print``(q[i].even)` `# Driver Code``q ``=` `[Query(``1``, ``3``, ``0``, ``0``),``     ``Query(``0``, ``4``, ``1``, ``0``),``     ``Query(``4``, ``7``, ``2``, ``0``)]``m ``=` `len``(q)` `queryResults(arr, n, q, m)``printResults(q, m)` `# This code is contributed by Tapesh (tapeshdua420)`

## C#

 `//  program to count of even``// digit sum elements in the given``// range using MO's algorithm``using` `System;``using` `System.Linq;``using` `System.Collections.Generic;` `// Class to represent a query range``public` `class` `Query``{``  ``public` `int` `L { ``get``; ``set``; }``  ``public` `int` `R { ``get``; ``set``; }``  ``public` `int` `Index { ``get``; ``set``; }``  ``public` `int` `Even { ``get``; ``set``; }` `  ``public` `Query(``int` `l, ``int` `r, ``int` `index, ``int` `even)``  ``{``    ``L = l;``    ``R = r;``    ``Index = index;``    ``Even = even;``  ``}``}` `public` `class` `GFG``{``  ``static` `int` `MAX = 100000;``  ``static` `int``[] arr = ``new` `int``[] { 5, 2, 3, 1, 4, 8, 10, 12 };``  ``static` `int` `n = arr.Length;`  `  ``// Variable to represent block size.``  ``// This is made here so compare()``  ``// of sort can use it``  ``static` `int` `block = (``int``)Math.Sqrt(n);`  `  ``// 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` `int` `Add(``int` `currL, ``int``[] a, ``int` `count_even)``  ``{` `    ``// If digit sum of a[currL]``    ``// is even then increment``    ``if` `(DigitSum(a[currL]) % 2 == 0)``    ``{``      ``count_even++;``    ``}``    ``return` `count_even;``  ``}`  `  ``// Function to remove elements``  ``// of previous range``  ``static` `int` `Remove(``int` `currR, ``int``[] a, ``int` `count_even)``  ``{` `    ``// If digit sum of a[currL]``    ``// is even then decrement``    ``if` `(DigitSum(a[currR]) % 2 == 0)``    ``{``      ``count_even--;``    ``}``    ``return` `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.``  ``static` `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;``    ``}``    ``else``    ``{``      ``// Same block, sort by R value``      ``return` `x.R - y.R;``    ``}``  ``}`  `  ``// 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``    ``int` `count_even = 0;` `    ``// Sort all queries so that queries of``    ``// same blocks are arranged together.``    ``q = q.OrderBy(x => x, Comparer.Create(Compare)).ToArray();` `    ``// 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)``      ``{``        ``count_even = Add(currR, a, count_even);``        ``currR++;``      ``}` `      ``while` `(currL > L)``      ``{``        ``count_even = Add(currL - 1, a, count_even);``        ``currL--;``      ``}` `      ``// Remove element of previous range``      ``while` `(currR > R + 1)``      ``{``        ``count_even = Remove(currR - 1, a, count_even);``        ``currR--;``      ``}` `      ``while` `(currL < L)``      ``{``        ``count_even = Remove(currL, a, count_even);``        ``currL++;``      ``}` `      ``q[i].Even = count_even;``    ``}``  ``}`  `  ``// Function to display the results of``  ``// queries in their initial order``  ``static` `void` `PrintResults(Query[] q, ``int` `m)``  ``{``    ``q = q.OrderBy(x => x.Index).ToArray();``    ``for` `(``int` `i = 0; i < m; i++)``    ``{``      ``Console.WriteLine(q[i].Even);``    ``}``  ``}` `  ``// Driver Code``  ``public` `static` `void` `Main()``  ``{``    ``Query[] q = ``new` `Query[] {``      ``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 shivhach999`

## Javascript

 `// Function to find the digit sum for a number``function` `digitSum(num) {``let sum = 0;``while` `(num) {``sum += (num % 10);``num = Math.floor(num / 10);``}``return` `sum;``}` `// Function to Add elements of current range``function` `add(currL, a, count_even) {``// If digit sum of a[currL] is even then increment``if` `(digitSum(a[currL]) % 2 === 0) {``count_even++;``}``return` `count_even;``}` `// Function to remove elements of previous range``function` `remove(currR, a, count_even) {``// If digit sum of a[currR] is even then decrement``if` `(digitSum(a[currR]) % 2 === 0) {``count_even--;``}``return` `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.``function` `compare(x, y) {``// Different blocks, sort by block.``if` `(Math.floor(x.L / block) !== Math.floor(y.L / block)) {``return` `Math.floor(x.L / block) < Math.floor(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``function` `compare1(x, y) {``return` `x.index < y.index;``}` `// Function to generate the result of queries``function` `queryResults(a, n, q, m) {``// Initialize number of even digit sum to 0``let count_even = 0;` `// Find block size``block = Math.floor(Math.sqrt(n));` `// Sort all queries so that queries of same blocks are arranged together.``q.sort(compare);` `// Initialize current L, current R and current result``let currL = 0, currR = 0;` `for` `(let i = 0; i < m; i++) {``// L and R values of current range``let L = q[i].L, R = q[i].R;` `// Add Elements of current range``while` `(currR <= R) {``  ``count_even = add(currR, a, count_even);``  ``currR++;``}``while` `(currL > L) {``  ``count_even = add(currL - 1, a, count_even);``  ``currL--;``}` `// Remove element of previous range``while` `(currR > R + 1) {``  ``count_even = remove(currR - 1, a, count_even);``  ``currR--;``}``while` `(currL < L) {``  ``count_even = remove(currL, a, count_even);``  ``currL++;``}` `q[i].even = count_even;``}``}` `// Function to display the results of queries in their initial order``function` `printResults(q, m) {``q.sort(compare1);``for` `(let i = 0; i < m; i++) {``document.write(q[i].even);``}``}` `// Driver Code``const arr = [5, 2, 3, 1, 4, 8, 10, 12];``const n = arr.length;` `const q = [``{ L: 1, R: 3, index: 0, even: 0 },``{ L: 0, R: 4, index: 1, even: 0 },``{ L: 4, R: 7, index: 2, even: 0 }]`  `    ``let m = q.length;` `    ``queryResults(arr, n, q, m);` `    ``printResults(q, m);`

Output
```1
2
2
```

Time Complexity: O(Q x ?N)
Auxiliary Space: O(1)

Previous
Next