Queries for the Count of Even Digit Sum Elements in the given Range using Segment Tree


Introduction

In this tutorial, we implement an approach in C++ to resolve queries for the count of even digit sum elements in the given range. We use a segment tree. To solve this task, we consider an array of elements with queries defining the range of the subarray. In that subarray count the even digit sum elements. Predefine the element array and the queries to resolve the problem using the Segment tree.

What is a segment tree?

A segment tree is a binary data structure that stores array interval or segment information. It efficiently solves range or segment query problems. Each node of the Segment tree represents a range of the array and the leaves represent array elements.

The key operations of the segment tree are Update and Range.

In this tutorial, we use the Segment Tree concept to resolve the queries of the element array.

Demonstration 1

Array = {1, 3, 4, 5, 6, 7, 8, 9}
Queries = [2, 5]

Output

2

Explanation

In the above input array, the starting index is 0. The queries define the input array indices. By considering the queries the revised sub-array is {4, 5, 6, 7}. In this subarray, there are 2 even sum digits, 4 and 6.

Demonstration 2

Array = {2, 8, 1, 5, 6, 7}
Queries = [1,3]

Output

1

Explanation

In the above input array, there are 6 elements, and the starting index number is 0. The query starts at indexes 1 to 3. The revised subarray using Queries is {8, 1, 5}. In this subarray, there is one even sum digit number 8.

C++ Library Functions

Syntax

vector : vector is a dynamic array in C++ that does not restrict array size. Inserting and deleting array elements is done efficiently with it. It is defined in the vector header file of the C++ library.

vector<data_type> vector_name;

sizeof(): it is a unary operator in C++. it helps in calculating the size of variables, constants, and data types during compile time.

sizeof(variable_name);

size(): It is a standard library function of C++. it returns the size of the input string.

string_name.size();

Algorithm

  • Consider an input array arr[] and define its elements.

  • Use this array to build a segment tree.

  • Each array element represents the leaves of the segment tree.

  • To build a segment tree, start with two array elements and divide the tree into two parts. Now take the third array element and insert it as per the Segment tree insertion rules. Similarly, insert all array elements.

  • Count the even sum digit elements by traversing the tree.

  • Initialize a counter variable and increase its count when an even sum digit element is found.

  • Print the counter variable result.

Example 1

Here, we implement the task with C++. Define a “constructSegmentTree” function to build a segment tree using the arr[] elements. Initialize the queries using the rangeBegin and RangeFinish variables and the function “querySegTree” computes the results according to the queries.

#include <iostream>
#include <vector>

using namespace std;

// Constructing the Segment tree node using structure
struct Node{
    int cnt;  // counter variable to count even digit sum elments
};

// Function to initialize the segment tree
void constructSegmentTree(const vector<int>& arr, vector<Node>& segtree, int node, int begin, int finish) {
    if (begin == finish) {
        // Leaf node
        segtree[node].cnt = (arr[begin] % 2 == 0) ? 1 : 0;
    } else {
        int between = (begin + finish) / 2;
        int lChild = 2 * node + 1;
        int rChild = 2 * node + 2;

        // Building substrees
        constructSegmentTree(arr, segtree, lChild, begin, between);
        constructSegmentTree(arr, segtree, rChild, between + 1, finish);

        // Combine results of left and right subtrees
        segtree[node].cnt = segtree[lChild].cnt + segtree[rChild].cnt;
    }
}

// query resolution function  
int querySegTree(const vector<Node>& segtree, int node, int begin, int finish, int rangeBegin, int rangeFinish) {
    if (begin > rangeFinish || finish < rangeBegin)
        return 0;

    if (rangeBegin <= begin && rangeFinish >= finish)
        return segtree[node].cnt;

    int between = (begin + finish) / 2;
    int lChild = 2 * node + 1;
    int rChild = 2 * node + 2;

    int lResult = querySegTree(segtree, lChild, begin, between, rangeBegin, rangeFinish);
    int rResult = querySegTree(segtree, rChild, between + 1, finish, rangeBegin, rangeFinish);

    return lResult + rResult;
}

// code controller
int main(){
    // vector array
    vector<int> arr = {2, 5, 3, 7, 6, 8, 1};
    int s = arr.size();

    vector<Node> segtree(4 * s); //defining the segment tree
    constructSegmentTree(arr, segtree, 0, 0, s - 1);

//queries
    int rangeBegin = 1;
    int rangeFinish = 4;
    int counter = querySegTree(segtree, 0, 0, s - 1, rangeBegin, rangeFinish);

    cout << "Count of elements with even digit sum in the range [" << rangeBegin << ", " << rangeFinish << "]: "<< counter << endl;

    return 0;
}

Output

Count of elements with even digit sum in the range [1, 4] : 1

Example 2

Here, we implement the task using C++. Initialize an array with all its elements. The predefined queries represent the indices of the array. Construct the Segment tree using the array element and user-defined function and count the number of even sum digits.

#include <bits/stdc++.h>
using namespace std;
 
int evenSumDigit(int n){
    int addition = 0;
    while (n){
        addition += (n % 10);
        n /= 10;
    }
 
    return addition;
}
 
// building the Segment Tree
void constructSegmentTree(vector<int>& segtree, int* a, int indexNo, int t, int f){
 
 //tree leaf node
    if (t == f){
        if (evenSumDigit(a[t]) & 1)
            segtree[indexNo] = 0;
        else
            segtree[indexNo] = 1;
        return;
    }
 
    int between = (t + f) / 2;
    constructSegmentTree(segtree, a, 2 * indexNo, t, between);
    constructSegmentTree(segtree, a, 2 * indexNo + 1,between + 1, f);
 
    segtree[indexNo] = segtree[2 * indexNo] + segtree[2 * indexNo + 1];
}
 
// processing queries
int queryArr(vector<int> segtree, int indexNo,int t, int f, int m, int q){

    if (q < t || m > f)
        return 0;
 
    if (t >= m && f <= q){
        return segtree[indexNo];
    }

    int between = (t + f) / 2;
    return (queryArr(segtree, 2 * indexNo, t, between, m, q) + queryArr(segtree, 2 * indexNo + 1,
                    between + 1, f, m, q));
}
 
// code controller
int main(){
    int a[] = { 7, 3, 19, 13, 5, 4 };
    int s = sizeof(a) / sizeof(a[0]);
    vector<int> segtree(4 * s + 1);
 
    int M = 2, S = 6;
 
    constructSegmentTree(segtree, a, 1, 0, s - 1);
 
    cout << "Number of even digit sum elements are: "<< queryArr(segtree, 1, 0, s - 1, M, S)
         << endl;
    return 0;
}

Output

Number of even digit sum elements are: 3

Conclusion

We have reached the end of this tutorial. Here, we find an approach to solving queries for the count of even digit sum elements in the given range through a Segment Tree. We implemented two ways to resolve the problem statement using the Segment tree. The demonstrations used in this tutorial elaborate on the problem statement's purpose.

Updated on: 18-Aug-2023

38 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements