Queries for the count of even digit sum elements in the given range using Segment Tree.
Last Updated :
28 Oct, 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 }
Output: 3
Explanation:
Elements 19, 13 and 4 have even digit sum
in the subarray {3, 9, 13, 5, 4}.
Input: arr[] = {0, 1, 2, 3, 4, 5, 6, 7}
query = { 3, 5 }
Output: 1
Explanation:
Only 4 has even digit sum
in the subarray {3, 4, 5}.
Naive approach:
- Find the answer for each query by simply traversing the array from index L till R and keep adding 1 to the count whenever the array element has even digit sum. Time Complexity of this approach will be O(n * q).
Efficient approach:
The idea is to build a Segment Tree.
- Representation of Segment trees:
- Leaf Nodes are the elements of the input array..
- Each internal node contains the number of leaves which has even digit sum of all leaves under it.
- Construction of Segment Tree from given array:
- We start with a segment arr[0 . . . n-1]. and every time we divide the current segment into two halves(if it has not yet become a segment of length 1) and then call the same procedure on both halves and for each such segment, we store the number of elements which has even digit sum of all nodes under it.
Below is the implementation of the above approach:
C++
// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
// 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;
}
// Procedure to build the segment tree
void buildTree(vector<int>& tree, int* arr,
int index, int s, int e)
{
// Reached the leaf node
// of the segment tree
if (s == e) {
if (digitSum(arr[s]) & 1)
tree[index] = 0;
else
tree[index] = 1;
return;
}
// Recursively call the buildTree
// on both the nodes of the tree
int mid = (s + e) / 2;
buildTree(tree, arr, 2 * index,
s, mid);
buildTree(tree, arr, 2 * index + 1,
mid + 1, e);
tree[index] = tree[2 * index]
+ tree[2 * index + 1];
}
// Query procedure to get the answer
// for each query l and r are
// query range
int query(vector<int> tree, int index,
int s, int e, int l, int r)
{
// Out of bound or no overlap
if (r < s || l > e)
return 0;
// Complete overlap
// Query range completely lies in
// the segment tree node range
if (s >= l && e <= r) {
return tree[index];
}
// Partially overlap
// Query range partially lies in
// the segment tree node range
int mid = (s + e) / 2;
return (query(tree, 2 * index, s,
mid, l, r)
+ query(tree, 2 * index + 1,
mid + 1, e, l, r));
}
// Driver code
int main()
{
int arr[] = { 7, 3, 19, 13, 5, 4 };
int n = sizeof(arr) / sizeof(arr[0]);
vector<int> tree(4 * n + 1);
int L = 1, R = 5;
buildTree(tree, arr, 1, 0, n - 1);
cout << query(tree, 1, 0, n - 1, L, R)
<< endl;
return 0;
}
Java
// Java implementation of the approach
import java.util.*;
class GFG{
// 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;
}
// Procedure to build the segment tree
static void buildTree(int []tree, int []arr,
int index, int s, int e)
{
// Reached the leaf node
// of the segment tree
if (s == e)
{
if (digitSum(arr[s]) % 2 == 1)
tree[index] = 0;
else
tree[index] = 1;
return;
}
// Recursively call the buildTree
// on both the nodes of the tree
int mid = (s + e) / 2;
buildTree(tree, arr, 2 * index,
s, mid);
buildTree(tree, arr, 2 * index + 1,
mid + 1, e);
tree[index] = tree[2 * index] +
tree[2 * index + 1];
}
// Query procedure to get the answer
// for each query l and r are
// query range
static int query(int []tree, int index,
int s, int e,
int l, int r)
{
// Out of bound or no overlap
if (r < s || l > e)
return 0;
// Complete overlap
// Query range completely lies in
// the segment tree node range
if (s >= l && e <= r)
{
return tree[index];
}
// Partially overlap
// Query range partially lies in
// the segment tree node range
int mid = (s + e) / 2;
return (query(tree, 2 * index, s,
mid, l, r) +
query(tree, 2 * index + 1,
mid + 1, e, l, r));
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 7, 3, 19, 13, 5, 4 };
int n = arr.length;
int []tree = new int[4 * n + 1];
int L = 1, R = 5;
buildTree(tree, arr, 1, 0, n - 1);
System.out.print(query(tree, 1, 0,
n - 1, L, R) + "\n");
}
}
// This code is contributed by gauravrajput1
Python3
# Python3 implementation of the above approach
# Function to find the digit sum
# for a number
def digitSum(num):
sum = 0;
while (num):
sum += (num % 10)
num //= 10
return sum
# Procedure to build the segment tree
def buildTree(tree, arr, index, s, e):
# Reached the leaf node
# of the segment tree
if (s == e):
if (digitSum(arr[s]) & 1):
tree[index] = 0
else:
tree[index] = 1
return
# Recursively call the buildTree
# on both the nodes of the tree
mid = (s + e) // 2
buildTree(tree, arr, 2 * index,
s, mid)
buildTree(tree, arr, 2 * index + 1,
mid + 1, e)
tree[index] = (tree[2 * index] +
tree[2 * index + 1])
# Query procedure to get the answer
# for each query l and r are
# query range
def query(tree, index, s, e, l, r):
# Out of bound or no overlap
if (r < s or l > e):
return 0
# Complete overlap
# Query range completely lies in
# the segment tree node range
if (s >= l and e <= r):
return tree[index]
# Partially overlap
# Query range partially lies in
# the segment tree node range
mid = (s + e) // 2
return (query(tree, 2 * index,
s, mid, l, r) +
query(tree, 2 * index + 1,
mid + 1, e, l, r))
# Driver code
arr = [ 7, 3, 19, 13, 5, 4 ]
n = len(arr)
tree = [0] * (4 * n + 1)
L = 1
R = 5
buildTree(tree, arr, 1, 0, n - 1);
print(query(tree, 1, 0, n - 1, L, R))
# This code is contributed by Apurvaraj
C#
// C# implementation of the approach
using System;
class GFG{
// 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;
}
// Procedure to build the segment tree
static void buildTree(int []tree, int []arr,
int index, int s, int e)
{
// Reached the leaf node
// of the segment tree
if (s == e)
{
if (digitSum(arr[s]) % 2 == 1)
tree[index] = 0;
else
tree[index] = 1;
return;
}
// Recursively call the buildTree
// on both the nodes of the tree
int mid = (s + e) / 2;
buildTree(tree, arr, 2 * index,
s, mid);
buildTree(tree, arr, 2 * index + 1,
mid + 1, e);
tree[index] = tree[2 * index] +
tree[2 * index + 1];
}
// Query procedure to get the answer
// for each query l and r are
// query range
static int query(int []tree, int index,
int s, int e,
int l, int r)
{
// Out of bound or no overlap
if (r < s || l > e)
return 0;
// Complete overlap
// Query range completely lies in
// the segment tree node range
if (s >= l && e <= r)
{
return tree[index];
}
// Partially overlap
// Query range partially lies in
// the segment tree node range
int mid = (s + e) / 2;
return (query(tree, 2 * index, s,
mid, l, r) +
query(tree, 2 * index + 1,
mid + 1, e, l, r));
}
// Driver code
public static void Main(String[] args)
{
int []arr = { 7, 3, 19, 13, 5, 4 };
int n = arr.Length;
int []tree = new int[4 * n + 1];
int L = 1, R = 5;
buildTree(tree, arr, 1, 0, n - 1);
Console.Write(query(tree, 1, 0,
n - 1, L, R) + "\n");
}
}
// This code is contributed by gauravrajput1
JavaScript
<script>
// JavaScript implementation of the approach
// Function to find the digit sum
// for a number
function digitSum(num) {
var sum = 0;
while (num > 0) {
sum += parseInt(num % 10);
num = parseInt(num / 10);
}
return sum;
}
// Procedure to build the segment tree
function buildTree(tree, arr, index, s, e) {
// Reached the leaf node
// of the segment tree
if (s === e) {
if (digitSum(arr[s]) % 2 === 1) tree[index] = 0;
else tree[index] = 1;
return;
}
// Recursively call the buildTree
// on both the nodes of the tree
var mid = parseInt((s + e) / 2);
buildTree(tree, arr, 2 * index, s, mid);
buildTree(tree, arr, 2 * index + 1, mid + 1, e);
tree[index] = tree[2 * index] + tree[2 * index + 1];
}
// Query procedure to get the answer
// for each query l and r are
// query range
function query(tree, index, s, e, l, r) {
// Out of bound or no overlap
if (r < s || l > e) return 0;
// Complete overlap
// Query range completely lies in
// the segment tree node range
if (s >= l && e <= r) {
return tree[index];
}
// Partially overlap
// Query range partially lies in
// the segment tree node range
var mid = (s + e) / 2;
return (
query(tree, 2 * index, s, mid, l, r) +
query(tree, 2 * index + 1, mid + 1, e, l, r)
);
}
// Driver code
var arr = [7, 3, 19, 13, 5, 4];
var n = arr.length;
var tree = new Array(4 * n + 1).fill(0);
var L = 1,
R = 5;
buildTree(tree, arr, 1, 0, n - 1);
document.write(query(tree, 1, 0, n - 1, L, R) + "<br>");
</script>
Time complexity: O(Q * log(N))
using Brute Force:
Approach:
We can solve this problem by iterating through each element in the given subarray and checking if its digit sum is even. We can count the number of such elements and return the count as the answer.
- The get_digit_sum function returns the digit sum of a given number.
- The count_even_digit_sum function takes an array arr and the left and right indices left and right of a subarray and counts the number of elements in the subarray that have an even digit sum.
- The count_even_digit_sum_queries function takes an array arr and a list of queries, where each query is a tuple of left and right indices, and returns a list of the number of elements with an even digit sum in each subarray specified by the queries.
C++
// Added by: Nikunj Sonigara
#include <bits/stdc++.h>
using namespace std; // Using the std namespace
int get_digit_sum(int num) {
// Returns the digit sum of the given number
int digit_sum = 0;
while (num > 0) {
digit_sum += num % 10;
num /= 10;
}
return digit_sum;
}
int count_even_digit_sum(const vector<int>& arr, int left, int right) {
// Counts the number of elements with even digit sum in the subarray [left, right]
int count = 0;
for (int i = left; i <= right; i++) {
if (get_digit_sum(arr[i]) % 2 == 0) {
count++;
}
}
return count;
}
vector<int> count_even_digit_sum_queries(const vector<int>& arr, const vector<pair<int, int>>& queries) {
// Counts the number of elements with even digit sum for each query
vector<int> results;
for (const auto& query : queries) {
int left = query.first;
int right = query.second;
results.push_back(count_even_digit_sum(arr, left, right));
}
return results;
}
int main() {
vector<int> arr = {7, 3, 19, 13, 5, 4};
vector<pair<int, int>> queries = {{1, 5}};
vector<int> results = count_even_digit_sum_queries(arr, queries);
cout << "[";
for (int i = 0; i < results.size(); i++) {
cout << results[i];
if (i < results.size() - 1) {
cout << ", ";
}
}
cout << "]" << endl;
arr = {0, 1, 2, 3, 4, 5, 6, 7};
queries = {{3, 5}};
results = count_even_digit_sum_queries(arr, queries);
cout << "[";
for (int i = 0; i < results.size(); i++) {
cout << results[i];
if (i < results.size() - 1) {
cout << ", ";
}
}
cout << "]" << endl;
return 0;
}
Java
// Added by: Nikunj Sonigara
import java.util.*;
public class Main {
static int getDigitSum(int num) {
// Returns the digit sum of the given number
int digitSum = 0;
while (num > 0) {
digitSum += num % 10;
num /= 10;
}
return digitSum;
}
static int countEvenDigitSum(List<Integer> arr, int left, int right) {
// Counts the number of elements with even digit sum in the subarray [left, right]
int count = 0;
for (int i = left; i <= right; i++) {
if (getDigitSum(arr.get(i)) % 2 == 0) {
count++;
}
}
return count;
}
static List<Integer> countEvenDigitSumQueries(List<Integer> arr, List<Pair<Integer, Integer>> queries) {
// Counts the number of elements with even digit sum for each query
List<Integer> results = new ArrayList<>();
for (Pair<Integer, Integer> query : queries) {
int left = query.getKey();
int right = query.getValue();
results.add(countEvenDigitSum(arr, left, right));
}
return results;
}
public static void main(String[] args) {
List<Integer> arr = List.of(7, 3, 19, 13, 5, 4);
List<Pair<Integer, Integer>> queries = List.of(new Pair<>(1, 5));
List<Integer> results = countEvenDigitSumQueries(arr, queries);
System.out.print("[");
for (int i = 0; i < results.size(); i++) {
System.out.print(results.get(i));
if (i < results.size() - 1) {
System.out.print(", ");
}
}
System.out.println("]");
arr = List.of(0, 1, 2, 3, 4, 5, 6, 7);
queries = List.of(new Pair<>(3, 5));
results = countEvenDigitSumQueries(arr, queries);
System.out.print("[");
for (int i = 0; i < results.size(); i++) {
System.out.print(results.get(i));
if (i < results.size() - 1) {
System.out.print(", ");
}
}
System.out.println("]");
}
}
class Pair<K, V> {
private final K key;
private final V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
}
Python3
def get_digit_sum(num):
# Returns the digit sum of the given number
digit_sum = 0
while num > 0:
digit_sum += num % 10
num //= 10
return digit_sum
def count_even_digit_sum(arr, left, right):
# Counts the number of elements with even digit sum in the subarray [left, right]
count = 0
for i in range(left, right+1):
if get_digit_sum(arr[i]) % 2 == 0:
count += 1
return count
def count_even_digit_sum_queries(arr, queries):
# Counts the number of elements with even digit sum for each query
results = []
for query in queries:
left, right = query
results.append(count_even_digit_sum(arr, left, right))
return results
arr = [7, 3, 19, 13, 5, 4]
queries = [(1, 5)]
print(count_even_digit_sum_queries(arr, queries)) # Output: [3]
arr = [0, 1, 2, 3, 4, 5, 6, 7]
queries = [(3, 5)]
print(count_even_digit_sum_queries(arr, queries)) # Output: [1]
C#
using System;
using System.Collections.Generic;
class Program
{
static int GetDigitSum(int num)
{
// Returns the digit sum of the given number
int digitSum = 0;
while (num > 0)
{
digitSum += num % 10;
num /= 10;
}
return digitSum;
}
static int CountEvenDigitSum(List<int> arr, int left, int right)
{
// Counts the number of elements with an even digit sum in the subarray [left, right]
int count = 0;
for (int i = left; i <= right; i++)
{
if (GetDigitSum(arr[i]) % 2 == 0)
{
count++;
}
}
return count;
}
static List<int> CountEvenDigitSumQueries(List<int> arr, List<Tuple<int, int>> queries)
{
// Counts the number of elements with an even digit sum for each query
List<int> results = new List<int>();
foreach (var query in queries)
{
int left = query.Item1;
int right = query.Item2;
results.Add(CountEvenDigitSum(arr, left, right));
}
return results;
}
static void Main()
{
List<int> arr = new List<int> { 7, 3, 19, 13, 5, 4 };
List<Tuple<int, int>> queries = new List<Tuple<int, int>> { Tuple.Create(1, 5) };
List<int> results = CountEvenDigitSumQueries(arr, queries);
Console.Write("[");
for (int i = 0; i < results.Count; i++)
{
Console.Write(results[i]);
if (i < results.Count - 1)
{
Console.Write(", ");
}
}
Console.WriteLine("]");
arr = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7 };
queries = new List<Tuple<int, int>> { Tuple.Create(3, 5) };
results = CountEvenDigitSumQueries(arr, queries);
Console.Write("[");
for (int i = 0; i < results.Count; i++)
{
Console.Write(results[i]);
if (i < results.Count - 1)
{
Console.Write(", ");
}
}
Console.WriteLine("]");
}
}
JavaScript
// Added by: Nikunj Sonigara
function getDigitSum(num) {
// Returns the digit sum of the given number
let digitSum = 0;
while (num > 0) {
digitSum += num % 10;
num = Math.floor(num / 10);
}
return digitSum;
}
function countEvenDigitSum(arr, left, right) {
// Counts the number of elements with even digit sum in the subarray [left, right]
let count = 0;
for (let i = left; i <= right; i++) {
if (getDigitSum(arr[i]) % 2 === 0) {
count++;
}
}
return count;
}
function countEvenDigitSumQueries(arr, queries) {
// Counts the number of elements with even digit sum for each query
const results = [];
for (const query of queries) {
const [left, right] = query;
results.push(countEvenDigitSum(arr, left, right));
}
return results;
}
const arr1 = [7, 3, 19, 13, 5, 4];
const queries1 = [[1, 5]];
const results1 = countEvenDigitSumQueries(arr1, queries1);
console.log(`[${results1}]`);
const arr2 = [0, 1, 2, 3, 4, 5, 6, 7];
const queries2 = [[3, 5]];
const results2 = countEvenDigitSumQueries(arr2, queries2);
console.log(`[${results2}]`);
The time complexity of this approach would be O(n*q), where n is the size of the input array and q is the number of queries.
The Auxiliary space would be O(1).
Similar Reads
Queries for elements greater than K in the given index range using Segment Tree
Given an array arr[] of N elements and a number of queries where each query will contain three integers L, R, and K. For each query, the task is to find the number of elements in the subarray arr[L...R] which are greater than K. Examples: Input: arr[] = {7, 3, 9, 13, 5, 4}, q[] = {{0, 3, 6}, {1, 5,
15+ min read
Queries to count numbers from a given range which are divisible the sum of their digits
Given an array Q[][] consisting of N queries of the form {L, R}, the task for each query is to find the total count of the numbers from the range [L, R] which are divisible by the sum of their digits. Examples: Input: Q[][]= {{5, 9}, {5, 20}}Output: 59Explanation: Query 1: The numbers in the range [
8 min read
Count the nodes in the given tree whose sum of digits of weight is odd
Given a tree, and the weights of all the nodes, the task is to count the number of nodes whose sum of digits of weights is odd.Examples: Input: Output: 3 Node 1: digitSum(144) = 1 + 4 + 4 = 9 Node 2: digitSum(1234) = 1 + 2 + 3 + 4 = 10 Node 3: digitSum(21) = 2 + 1 = 3 Node 4: digitSum(5) = 5 Node 5:
6 min read
Count numbers in given range such that sum of even digits is greater than sum of odd digits
Given two integers l and r denoting a range [l, r]. The task is to find the total count of numbers in the given range [l, r] whose sum of even digits is greater than the sum of odd digits. Examples:Input: l = 2, r = 10 Output : 4Explanation: Numbers having the property that sum of even digits is gre
15+ min read
Find the maximum Even Digit Sum node in the given tree
Given a tree with the weights of all the nodes, the task is to find the maximum weighing node whose weight has even digit sum. Examples: Input: Tree = 5 / \ 10 6 / \ 11 8 Output: 11 Explanation: The tree node weights are: 5 -> 5 10 -> 1 + 0 = 1 6 -> 6 11 -> 1 + 1 = 2 8 -> 8 Here, digi
7 min read
Segment Tree for Range Assignment and Range Sum Queries
Given an array of size N filled with all 0s, the task is to answer Q queries, where the queries can be one of the two types: Type 1 (1, L, R, X): Assign value X to all elements on the segment from L to Râ1, andType 2 (2, L, R): Find the sum on the segment from L to Râ1.Examples: Input: N = 5, Q = 3,
15+ min read
Count numbers (smaller than or equal to N) with given digit sum
Given a number N and a sum S, find the count of numbers upto N that have digit sum equal to S. Examples: Input : N = 100, S = 4 Output : 5 Upto 100 only 5 numbers(4, 13, 22, 31, 40) can produce 4 as their sum of digits. Input : N = 1000, S = 1 Output : 4 Upto 1000 only 4 numbers(1, 10, 100 and 1000)
8 min read
Queries to calculate sum by alternating signs of array elements in a given range
Given an array arr[] of size N and a 2D array Q[][], consisting of queries of the following two types: 1 X Val: Update arr[X] = Val.2 L R: Find the sum of array elements with alternating signs in the range [L, R]. Examples: Input: arr[] = { 1, 2, 3, 4 }, Q[][] = { { 2, 0, 3 }, { 1, 1, 5 }, { 2, 1, 2
15+ min read
Count the nodes in the given tree whose weight is even
Given a tree, and the weights of all the nodes, the task is to count the number of nodes whose weight is even.Examples: Input: Output: 3 Only the weights of the nodes 2, 4 and 5 are even. Approach: Perform dfs on the tree and for every node, check if it's weight is divisible by 2 or not. If yes then
5 min read
Count pairs in an array having sum of elements with their respective sum of digits equal
Given an array arr[] consisting of N positive integers, the task is to count the number of pairs in the array, say (a, b) such that sum of a with its sum of digits is equal to sum of b with its sum of digits. Examples: Input: arr[] = {1, 1, 2, 2}Output: 2Explanation:Following are the pairs that sati
8 min read