给定一个包含N 个元素的数组arr[] ,任务是回答 Q 个查询,每个查询都有两个整数L和R 。对于每个查询,任务是找到子数组arr[L…R] 中数字和为偶数的元素的数量。
例子:
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}.
幼稚的方法:
- 通过简单地从索引L到R遍历数组来找到每个查询的答案,并在数组元素具有偶数位总和时继续将计数加1 。这种方法的时间复杂度为O(n * q) 。
有效的方法:
这个想法是建立一个段树。
- 段树的表示:
- 叶节点是输入数组的元素。
- 每个内部节点包含叶子的数量,其下所有叶子的总和为偶数。
- 从给定数组构建段树:
- 我们从一个段 arr[0 开始。 . . n-1]。每次我们将当前段分成两半(如果它还没有成为长度为 1 的段)然后在两半和每个这样的段上调用相同的过程,我们存储具有偶数和的元素的数量它下的所有节点。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
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& 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 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 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
输出:
3
时间复杂度: O(Q * log(N))
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live