 Open in App
Not now

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

• Last Updated : 21 Mar, 2023

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`

## 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)`

## 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)

My Personal Notes arrow_drop_up
Related Articles