给定一个由N 个正整数组成的数组arr[]和一个由{L, R}形式的Q 个查询组成的数组Query[][2] ,任务是找到范围[L, R] ,有奇数个除数。
例子:
Input: arr[] = {2, 4, 5, 6, 9}, Q = 3, Query[][] = {{0, 2}, {1, 3}, {1, 4}}
Output: 4 4 13
Explanation:
Query 1: Elements from indices [0, 2] are {2, 4, 5}. Out of them, only 4 has odd number of divisors. Therefore, the sum is 4.
Query 2: Elements from indices [1, 3] are {4, 5, 6}. Out of them, only 4 has odd number of divisors. Therefore, the sum is 4.
Query 3: Elements from the indices [1, 4] are {4, 5, 6, 9}. Out of them, only 4, 9 has odd number of divisors. Therefore, the sum is 13.
Input: arr[] = {1, 16, 5, 4, 9}, Q = 2, Query[][] = {{1, 3}, {0, 2}}
Output: 20 17
朴素的方法:解决给定问题的最简单方法是为每个查询在范围[L, R]上遍历给定数组arr[]并找到范围[L, R] 中具有奇数个元素的总和除数,并打印结果和。
时间复杂度: O(Q * N *√N)
辅助空间: O(1)
高效方法:上述方法也可以基于以下观察进行优化:
- 仅当数字是完全平方数时,除数的数量才为奇数。
- 因此,可以通过将除数不是奇数的整数替换为 0 来解决问题。然后,构建一个段树,找到范围内元素的总和来回答查询。
请按照以下步骤解决问题:
- 遍历给定的数组arr[]并将不是完全平方的整数替换为0 。
- 构建一个段树来回答范围之间的求和查询。
- 遍历所有Q查询,对于每个查询,从段树中获取特定范围的总和。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to get the middle index
// from the given ranges
int getMid(int s, int e)
{
return s + (e - s) / 2;
}
// Recursive function to find the sum
// of values in the given range of
// the array
int getSumUtil(int* st, int ss, int se,
int qs, int qe, int si)
{
// If segment of this node is a
// part of given range, then
// return the sum of the segment
if (qs <= ss && qe >= se)
return st[si];
// If segment of this node is
// outside the given range
if (se < qs || ss > qe)
return 0;
// If a part of this segment
// overlaps the given range
int mid = getMid(ss, se);
return getSumUtil(st, ss, mid,
qs, qe, 2 * si + 1)
+ getSumUtil(st, mid + 1,
se, qs, qe,
2 * si + 2);
}
// Function to find the sum of elements
// in the range from index qs (query
// start) to qe (query end)
int getSum(int* st, int n, int qs, int qe)
{
// Invalid ranges
if (qs < 0 || qe > n - 1 || qs > qe) {
cout << "Invalid Input";
return -1;
}
return getSumUtil(st, 0, n - 1, qs, qe, 0);
}
// Recursive function to construct the
// Segment Tree for array[ss..se]. si
// is index of current node in tree st
int constructSTUtil(int arr[], int ss,
int se, int* st,
int si)
{
// If there is one element
// in the array
if (ss == se) {
st[si] = arr[ss];
return arr[ss];
}
int mid = getMid(ss, se);
// Recur for left and right
// subtrees and store the sum
// of values in this node
st[si] = constructSTUtil(arr, ss, mid,
st, si * 2 + 1)
+ constructSTUtil(arr, mid + 1,
se, st,
si * 2 + 2);
return st[si];
}
// Function to construct segment tree
// from the given array
int* constructST(int arr[], int n)
{
// Allocate memory for the segment
// tree Height of segment tree
int x = (int)(ceil(log2(n)));
// Maximum size of segment tree
int max_size = 2 * (int)pow(2, x) - 1;
// Allocate memory
int* st = new int[max_size];
// Fill the allocated memory st
constructSTUtil(arr, 0, n - 1, st, 0);
// Return the constructed
// segment tree
return st;
}
// Function to find the sum of elements
// having odd number of divisors in
// index range [L, R] for Q queries
void OddDivisorsSum(int n, int q, int arr[],
vector > Query)
{
// Traverse the array, arr[]
for (int i = 0; i < n; i++) {
int sq = sqrt(arr[i]);
// Replace elements that are
// not perfect squares with 0
if (sq * sq != arr[i])
arr[i] = 0;
}
// Build segment tree from the
// given array
int* st = constructST(arr, n);
// Iterate through all the queries
for (int i = 0; i < q; i++) {
int l = Query[i].first;
int r = Query[i].second;
// Print sum of values in
// array from index l to r
cout << getSum(st, n, l, r) << " ";
}
}
// Driver Code
int main()
{
int arr[] = { 2, 4, 5, 6, 9 };
int N = sizeof(arr) / sizeof(arr[0]);
int Q = 3;
vector > Query
= { { 0, 2 }, { 1, 3 }, { 1, 4 } };
OddDivisorsSum(N, Q, arr, Query);
return 0;
}
Java
// java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
public class GFG {
// Function to get the middle index
// from the given ranges
static int getMid(int s, int e)
{
return s + (e - s) / 2;
}
// Recursive function to find the sum
// of values in the given range of
// the array
static int getSumUtil(int st[], int ss, int se, int qs,
int qe, int si)
{
// If segment of this node is a
// part of given range, then
// return the sum of the segment
if (qs <= ss && qe >= se)
return st[si];
// If segment of this node is
// outside the given range
if (se < qs || ss > qe)
return 0;
// If a part of this segment
// overlaps the given range
int mid = getMid(ss, se);
return getSumUtil(st, ss, mid, qs, qe, 2 * si + 1)
+ getSumUtil(st, mid + 1, se, qs, qe,
2 * si + 2);
}
// Function to find the sum of elements
// in the range from index qs (query
// start) to qe (query end)
static int getSum(int st[], int n, int qs, int qe)
{
// Invalid ranges
if (qs < 0 || qe > n - 1 || qs > qe) {
System.out.println("Invalid Input");
return -1;
}
return getSumUtil(st, 0, n - 1, qs, qe, 0);
}
// Recursive function to construct the
// Segment Tree for array[ss..se]. si
// is index of current node in tree st
static int constructSTUtil(int arr[], int ss, int se,
int st[], int si)
{
// If there is one element
// in the array
if (ss == se) {
st[si] = arr[ss];
return arr[ss];
}
int mid = getMid(ss, se);
// Recur for left and right
// subtrees and store the sum
// of values in this node
st[si]
= constructSTUtil(arr, ss, mid, st, si * 2 + 1)
+ constructSTUtil(arr, mid + 1, se, st,
si * 2 + 2);
return st[si];
}
// Function to construct segment tree
// from the given array
static int[] constructST(int arr[], int n)
{
// Allocate memory for the segment
// tree Height of segment tree
int x = (int)(Math.ceil(Math.log(n) / Math.log(2)));
// Maximum size of segment tree
int max_size = 2 * (int)Math.pow(2, x) - 1;
// Allocate memory
int st[] = new int[max_size];
// Fill the allocated memory st
constructSTUtil(arr, 0, n - 1, st, 0);
// Return the constructed
// segment tree
return st;
}
// Function to find the sum of elements
// having odd number of divisors in
// index range [L, R] for Q queries
static void OddDivisorsSum(int n, int q, int arr[],
int Query[][])
{
// Traverse the array, arr[]
for (int i = 0; i < n; i++) {
int sq = (int)Math.sqrt(arr[i]);
// Replace elements that are
// not perfect squares with 0
if (sq * sq != arr[i])
arr[i] = 0;
}
// Build segment tree from the
// given array
int st[] = constructST(arr, n);
// Iterate through all the queries
for (int i = 0; i < q; i++) {
int l = Query[i][0];
int r = Query[i][1];
// Print sum of values in
// array from index l to r
System.out.print(getSum(st, n, l, r) + " ");
}
}
// Driver Code
public static void main(String[] args)
{
int arr[] = { 2, 4, 5, 6, 9 };
int N = arr.length;
int Q = 3;
int Query[][] = { { 0, 2 }, { 1, 3 }, { 1, 4 } };
OddDivisorsSum(N, Q, arr, Query);
}
}
// This code is contributed by Kingash.
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the sum of elements
// having odd number of divisors in
// index range [L, R] for Q queries
void OddDivisorsSum(int n, int q, int a[],
vector > Query)
{
// Initialize the dp[] array
int DP[n] = { 0 };
// Traverse the array, arr[]
for (int i = 0; i < n; i++) {
int x = sqrt(a[i]);
// If a[i] is a perfect square,
// then update value of DP[i] to a[i]
if (x * x == a[i])
DP[i] = a[i];
}
// Find the prefix sum of DP[] array
for (int i = 1; i < n; i++) {
DP[i] = DP[i - 1] + DP[i];
}
// Iterate through all the queries
for (int i = 0; i < q; i++) {
int l = Query[i].first;
int r = Query[i].second;
// Find the sum for each query
if (l == 0) {
cout << DP[r] << " ";
}
else {
cout << DP[r] - DP[l - 1]
<< " ";
}
}
}
// Driver Code
int main()
{
int arr[] = { 2, 4, 5, 6, 9 };
int N = sizeof(arr) / sizeof(arr[0]);
int Q = 3;
vector > Query
= { { 0, 2 }, { 1, 3 }, { 1, 4 } };
OddDivisorsSum(N, Q, arr, Query);
return 0;
}
Python3
# Python3 program for the above approach
from math import sqrt
# Function to find the sum of elements
# having odd number of divisors in
# index range [L, R] for Q queries
def OddDivisorsSum(n, q, a, Query):
# Initialize the dp[] array
DP = [0]*n
# Traverse the array, arr[]
for i in range(n):
x = sqrt(a[i])
# If a[i] is a perfect square,
# then update value of DP[i] to a[i]
if (x * x == a[i]):
DP[i] = a[i]
# Find the prefix sum of DP[] array
for i in range(1, n):
DP[i] = DP[i - 1] + DP[i]
# Iterate through all the queries
for i in range(q):
l = Query[i][0]
r = Query[i][1]
# Find the sum for each query
if (l == 0):
print(DP[r], end=" ")
else:
print(DP[r] - DP[l - 1], end=" ")
# Driver Code
if __name__ == '__main__':
arr = [2, 4, 5, 6, 9]
N = len(arr)
Q = 3
Query = [ [ 0, 2 ], [ 1, 3 ], [ 1, 4 ] ]
OddDivisorsSum(N, Q, arr, Query)
# This code is contributed by mohit kumar 29.
C#
// C# program for the above approach
using System;
class GFG
{
// Function to find the sum of elements
// having odd number of divisors in
// index range [L, R] for Q queries
static void OddDivisorsSum(int n, int q, int[] a,
int[, ] Query)
{
// Initialize the dp[] array
int[] DP = new int[n];
// Traverse the array, arr[]
for (int i = 0; i < n; i++) {
int x = (int)(Math.Sqrt(a[i]));
// If a[i] is a perfect square,
// then update value of DP[i] to a[i]
if (x * x == a[i])
DP[i] = a[i];
}
// Find the prefix sum of DP[] array
for (int i = 1; i < n; i++) {
DP[i] = DP[i - 1] + DP[i];
}
// Iterate through all the queries
for (int i = 0; i < q; i++) {
int l = Query[i, 0];
int r = Query[i, 1];
// Find the sum for each query
if (l == 0) {
Console.Write(DP[r] + " ");
}
else {
Console.Write(DP[r] - DP[l - 1] + " ");
}
}
}
// Driver Code
public static void Main()
{
int[] arr = { 2, 4, 5, 6, 9 };
int N = arr.Length;
int Q = 3;
int[, ] Query = { { 0, 2 }, { 1, 3 }, { 1, 4 } };
OddDivisorsSum(N, Q, arr, Query);
}
}
// This code is contributed by ukasp.
4 4 13
时间复杂度: O(Q * log(N))
辅助空间: O(N)
高效的方法:为了优化上述方法,想法是使用一个辅助数组来存储具有奇数个除数的元素的前缀和。请按照以下步骤解决问题:
- 用0初始化大小为N的数组dp[] 。
- 使用变量i遍历给定的数组arr[]并检查是否有任何元素是完美正方形。如果发现为真,则将dp[i]的值更新为arr[i] 。
- 查找数组dp[]的前缀和。
- 遍历所有查询,对于[L, R]范围内的每个查询,答案将由(dp[R] – dp[L – 1]) 给出。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the sum of elements
// having odd number of divisors in
// index range [L, R] for Q queries
void OddDivisorsSum(int n, int q, int a[],
vector > Query)
{
// Initialize the dp[] array
int DP[n] = { 0 };
// Traverse the array, arr[]
for (int i = 0; i < n; i++) {
int x = sqrt(a[i]);
// If a[i] is a perfect square,
// then update value of DP[i] to a[i]
if (x * x == a[i])
DP[i] = a[i];
}
// Find the prefix sum of DP[] array
for (int i = 1; i < n; i++) {
DP[i] = DP[i - 1] + DP[i];
}
// Iterate through all the queries
for (int i = 0; i < q; i++) {
int l = Query[i].first;
int r = Query[i].second;
// Find the sum for each query
if (l == 0) {
cout << DP[r] << " ";
}
else {
cout << DP[r] - DP[l - 1]
<< " ";
}
}
}
// Driver Code
int main()
{
int arr[] = { 2, 4, 5, 6, 9 };
int N = sizeof(arr) / sizeof(arr[0]);
int Q = 3;
vector > Query
= { { 0, 2 }, { 1, 3 }, { 1, 4 } };
OddDivisorsSum(N, Q, arr, Query);
return 0;
}
蟒蛇3
# Python3 program for the above approach
from math import sqrt
# Function to find the sum of elements
# having odd number of divisors in
# index range [L, R] for Q queries
def OddDivisorsSum(n, q, a, Query):
# Initialize the dp[] array
DP = [0]*n
# Traverse the array, arr[]
for i in range(n):
x = sqrt(a[i])
# If a[i] is a perfect square,
# then update value of DP[i] to a[i]
if (x * x == a[i]):
DP[i] = a[i]
# Find the prefix sum of DP[] array
for i in range(1, n):
DP[i] = DP[i - 1] + DP[i]
# Iterate through all the queries
for i in range(q):
l = Query[i][0]
r = Query[i][1]
# Find the sum for each query
if (l == 0):
print(DP[r], end=" ")
else:
print(DP[r] - DP[l - 1], end=" ")
# Driver Code
if __name__ == '__main__':
arr = [2, 4, 5, 6, 9]
N = len(arr)
Q = 3
Query = [ [ 0, 2 ], [ 1, 3 ], [ 1, 4 ] ]
OddDivisorsSum(N, Q, arr, Query)
# This code is contributed by mohit kumar 29.
C#
// C# program for the above approach
using System;
class GFG
{
// Function to find the sum of elements
// having odd number of divisors in
// index range [L, R] for Q queries
static void OddDivisorsSum(int n, int q, int[] a,
int[, ] Query)
{
// Initialize the dp[] array
int[] DP = new int[n];
// Traverse the array, arr[]
for (int i = 0; i < n; i++) {
int x = (int)(Math.Sqrt(a[i]));
// If a[i] is a perfect square,
// then update value of DP[i] to a[i]
if (x * x == a[i])
DP[i] = a[i];
}
// Find the prefix sum of DP[] array
for (int i = 1; i < n; i++) {
DP[i] = DP[i - 1] + DP[i];
}
// Iterate through all the queries
for (int i = 0; i < q; i++) {
int l = Query[i, 0];
int r = Query[i, 1];
// Find the sum for each query
if (l == 0) {
Console.Write(DP[r] + " ");
}
else {
Console.Write(DP[r] - DP[l - 1] + " ");
}
}
}
// Driver Code
public static void Main()
{
int[] arr = { 2, 4, 5, 6, 9 };
int N = arr.Length;
int Q = 3;
int[, ] Query = { { 0, 2 }, { 1, 3 }, { 1, 4 } };
OddDivisorsSum(N, Q, arr, Query);
}
}
// This code is contributed by ukasp.
4 4 13
时间复杂度: O(N)
辅助空间: O(N)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live