// 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<Query>.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