Given an array arr[] consisting of N positive integers and an array Query[][2] consisting of Q queries of the form {L, R}, the task is to find the sum of all array elements from the range [L, R], having odd number of divisors.
Examples:
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
Naive Approach: The simplest approach is to solve the given problem is to traverse the given array arr[] over the range [L, R] for each query and find the sum of elements in the range [L, R] having odd numbers of divisors, and print the resultant sum.
Time Complexity: O(Q * N *?N)
Auxiliary Space: O(1)
Efficient Approach: The above approach can also be optimized which is based on the below observation:
- The number of divisors is odd only if the number is perfect squares.
- So, the problem can be solved by replacing the integers that do not have an odd number of divisors with 0. Then, build a segment tree that finds the sum of elements in the range to answer the queries.
Follow the steps below to solve the problem:
- Traverse the given array arr[] and replace the integers that are not perfect squares with 0.
- Build a segment tree to answer the sum queries between the range.
- Iterate through all the Q queries, and for each query, get the sum of the particular range from the segment tree.
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> 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<pair< int , int > > 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<pair< int , int > > Query
= { { 0, 2 }, { 1, 3 }, { 1, 4 } };
OddDivisorsSum(N, Q, arr, Query);
return 0;
} |
// 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. |
import math
# Function to get the middle index # from the given ranges def get_mid(s, e):
return s + math.floor((e - s) / 2 )
# Recursive function to find the sum # of values in the given range of # the array def get_sum_util(st, ss, se, qs, qe, si):
# If segment of this node is a
# part of given range, then
# return the sum of the segment
if qs < = ss and qe > = se:
return st[si]
# If segment of this node is
# outside the given range
if se < qs or ss > qe:
return 0
# If a part of this segment
# overlaps the given range
mid = get_mid(ss, se)
return get_sum_util(st, ss, mid, qs, qe, 2 * si + 1 ) + \
get_sum_util(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) def get_sum(st, n, qs, qe):
# Invalid ranges
if qs < 0 or qe > n - 1 or qs > qe:
return - 1
return get_sum_util(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 def construct_st_util(arr, ss, se, st, si):
# If there is one element
# in the array
if ss = = se:
st[si] = arr[ss]
return arr[ss]
mid = get_mid(ss, se)
# Recur for left and right
# subtrees and store the sum
# of values in this node
st[si] = construct_st_util(arr, ss, mid, st, si * 2 + 1 ) + \
construct_st_util(arr, mid + 1 , se, st, si * 2 + 2 )
return st[si]
# Function to construct segment tree # from the given array def construct_st(arr, n):
# Allocate memory for the segment
# tree Height of segment tree
x = math.ceil(math.log(n) / math.log( 2 ))
# Maximum size of segment tree
max_size = 2 * math. pow ( 2 , x) - 1
# Allocate memory
st = [ 0 ] * int (max_size)
# Fill the allocated memory st
construct_st_util(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 def odd_divisors_sum(n, q, arr, Query):
# Traverse the array,
for i in range (n):
sq = arr[i] * * 0.5
# Replace elements that are
# not perfect squares with 0
if (sq * sq ! = arr[i]):
arr[i] = 0 ;
# Build segment tree from the
# given array
st = construct_st(arr, n);
# Iterate through all the queries
for i in range (q):
l, r = Query[i][ 0 ], Query[i][ 1 ]
# Print sum of values in
# array from index l to r
print (get_sum(st, n, l, r), end = " " );
print ()
# Driver Code arr = [ 2 , 4 , 5 , 6 , 9 ];
N = len (arr);
Q = 3 ;
Query = [[ 0 , 2 ], [ 1 , 3 ], [ 1 , 4 ]];
odd_divisors_sum(N, Q, arr, Query); # This code is contributed by phasing17. |
// C# program for the above approach using System;
using System.Linq;
using System.Collections.Generic;
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) {
Console.WriteLine( "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.Ceiling(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
Console.Write(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 = { new int [] { 0, 2 }, new int [] { 1, 3 }, new int [] { 1, 4 } };
OddDivisorsSum(N, Q, arr, Query);
}
} // This code is contributed by phasing17. |
<script> // JavaScript program for the above approach // Function to get the middle index // from the given ranges function getMid(s,e)
{ return s + Math.floor((e - s) / 2);
} // Recursive function to find the sum // of values in the given range of // the array function getSumUtil(st,ss,se,qs,qe,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
let 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)
function getSum( st, n, qs, qe)
{
// Invalid ranges
if (qs < 0 || qe > n - 1 || qs > qe) {
document.write( "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 function constructSTUtil(arr,ss,se,st,si)
{ // If there is one element
// in the array
if (ss == se) {
st[si] = arr[ss];
return arr[ss];
}
let 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
function constructST(arr,n)
{ // Allocate memory for the segment
// tree Height of segment tree
let x = (Math.ceil(Math.log(n) / Math.log(2)));
// Maximum size of segment tree
let max_size = 2 * Math.pow(2, x) - 1;
// Allocate memory
let st = new Array(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
function OddDivisorsSum(n,q,arr,Query)
{ // Traverse the array, arr[]
for (let i = 0; i < n; i++) {
let sq = 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
let st = constructST(arr, n);
// Iterate through all the queries
for (let i = 0; i < q; i++) {
let l = Query[i][0];
let r = Query[i][1];
// Print sum of values in
// array from index l to r
document.write(getSum(st, n, l, r) + " " );
}
} // Driver Code
let arr=[2, 4, 5, 6, 9]; let N = arr.length; let Q = 3; let Query=[[ 0, 2 ], [ 1, 3 ], [ 1, 4 ]]; OddDivisorsSum(N, Q, arr, Query); // This code is contributed by avanitrachhadiya2155 </script> |
4 4 13
Time Complexity: O(Q * log(N))
Auxiliary Space: O(N)
Efficient Approach: To optimize the above approach, the idea is to use an auxiliary array that stores the prefix sum of elements having an odd number of divisors. Follow the steps below to solve the problem:
- Initialize an array dp[] of size N with 0.
- Traverse the given array arr[] using the variable i and check if any element is a perfect square. If found to be true, then update the value of dp[i] as arr[i].
- Find the prefix sum of the array dp[].
- Iterate through all the queries and for each query in the range [L, R] the answer will be given by (dp[R] – dp[L – 1]).
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> 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<pair< int , int > > 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<pair< int , int > > Query
= { { 0, 2 }, { 1, 3 }, { 1, 4 } };
OddDivisorsSum(N, Q, arr, Query);
return 0;
} |
/*package whatever //do not write package name here */ import java.io.*;
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 ) {
System.out.print(DP[r] + " " );
}
else {
System.out.print(DP[r] - DP[l - 1 ] + " " );
}
}
}
// 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);
}
} |
# 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# 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. |
<script> // Javascript program for the above approach // Function to find the sum of elements // having odd number of divisors in // index range [L, R] for Q queries function OddDivisorsSum(n, q, a, Query)
{ // Initialize the dp[] array
let DP = new Array(n);
for (let i = 0; i < n; i++)
{
DP[i] = 0;
}
// Traverse the array, arr[]
for (let i = 0; i < n; i++)
{
let x = Math.floor(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 (let i = 1; i < n; i++)
{
DP[i] = DP[i - 1] + DP[i];
}
// Iterate through all the queries
for (let i = 0; i < q; i++)
{
let l = Query[i][0];
let r = Query[i][1];
// Find the sum for each query
if (l == 0)
{
document.write(DP[r] + " " );
}
else
{
document.write(DP[r] - DP[l - 1] + " " );
}
}
} // Driver Code let arr = [ 2, 4, 5, 6, 9 ]; let N = arr.length; let Q = 3 let Query = [ [ 0, 2 ], [ 1, 3 ],
[ 1, 4 ] ];
OddDivisorsSum(N, Q, arr, Query); // This code is contributed by patel2127 </script> |
4 4 13
Time complexity: O(N+Q)
Auxiliary Space: O(N)