Find sum of product of every number and its frequency in given range
Given an array arr[] of integers and an array of queries, the task is to find the sum of product of every number and its frequency in given range [L, R] where each ranges are given in the array of queries.
Examples:
Input: arr[] = [1, 2, 1], Queries: [{1, 2}, {1, 3}]
Output: [3, 4]
Explanation:
For query [1, 2], freq[1] = 1, freq[2] = 1, ans = (1 * freq[1]) + (2 * freq[2]) => ans = (1 * 1 + 2 * 1) = 3
For query [1, 3], freq[1] = 2, freq[2] = 1; ans = (1 * freq[1]) + (2 * freq[2]) => ans = (1 * 2) + (2 * 1) = 4Input: arr[] = [1, 1, 2, 2, 1, 3, 1, 1], Queries: [{2, 7}, {1, 6}]
Output: [10, 10]
Explanation:
For query (2, 7), freq[1] = 3, freq[2] = 2, freq[3] = 3;
ans = (1 * freq[1]) + (2 * freq[2] ) + (3 * freq[3])
ans = (1 * 3) + (2 * 2) + (3 * 1) = 10
Naive Approach:
To solve the problem mentioned above the naive method is to iterate over the subarray given in the query. Maintain a map for the frequency of each number in the subarray and iterate over the map and compute the answer.
Below is the implementation of the above approach:
C++
// C++ implementation to find // sum of product of every number // and square of its frequency // in the given range #include <bits/stdc++.h> using namespace std; // Function to solve queries void answerQueries( int arr[], int n, vector<pair< int , int > >& queries) { for ( int i = 0; i < queries.size(); i++) { // Calculating answer // for every query int ans = 0; // The end points // of the ith query int l = queries[i].first - 1; int r = queries[i].second - 1; // map for storing frequency map< int , int > freq; for ( int j = l; j <= r; j++) { // Iterating over the given // subarray and storing // frequency in a map // Incrementing the frequency freq[arr[j]]++; } // Iterating over map to find answer for ( auto & i : freq) { // adding the contribution // of ith number ans += (i.first * i.second); } // print answer cout << ans << endl; } } // Driver code int main() { int arr[] = { 1, 2, 1 }; int n = sizeof (arr) / sizeof (arr[0]); vector<pair< int , int > > queries = { { 1, 2 }, { 1, 3 } }; answerQueries(arr, n, queries); } |
Java
// Java program to find sum of // product of every number and // square of its frequency in // the given range import java.util.*; class GFG{ // Function to solve queries public static void answerQueries( int [] arr, int n, int [][] queries) { for ( int i = 0 ; i < queries.length; i++) { // Calculating answer // for every query int ans = 0 ; // The end points // of the ith query int l = queries[i][ 0 ] - 1 ; int r = queries[i][ 1 ] - 1 ; // Hashmap for storing frequency Map<Integer, Integer> freq = new HashMap<>(); for ( int j = l; j < r + 1 ; j++) { // Iterating over the given // subarray and storing // frequency in a map // Incrementing the frequency freq.put(arr[j], freq.getOrDefault(arr[j], 0 ) + 1 ); } for ( int k: freq.keySet()) { // Adding the contribution // of ith number ans += k * freq.get(k); } // Print answer System.out.println(ans); } } // Driver code public static void main(String args[] ) { int [] arr = { 1 , 2 , 1 }; int n = arr.length; int [][] queries = { { 1 , 2 }, { 1 , 3 } }; // Calling function answerQueries(arr, n, queries); } } // This code contributed by dadi madhav |
Python3
# Python3 implementation to find # sum of product of every number # and square of its frequency # in the given range # Function to solve queries def answerQueries(arr, n, queries): for i in range ( len (queries)): # Calculating answer # for every query ans = 0 # The end points # of the ith query l = queries[i][ 0 ] - 1 r = queries[i][ 1 ] - 1 # Map for storing frequency freq = dict () for j in range (l, r + 1 ): # Iterating over the given # subarray and storing # frequency in a map # Incrementing the frequency freq[arr[j]] = freq.get(arr[j], 0 ) + 1 # Iterating over map to find answer for i in freq: # Adding the contribution # of ith number ans + = (i * freq[i]) # Print answer print (ans) # Driver code if __name__ = = '__main__' : arr = [ 1 , 2 , 1 ] n = len (arr) queries = [ [ 1 , 2 ], [ 1 , 3 ] ] answerQueries(arr, n, queries) # This code is contributed by mohit kumar 29 |
C#
// C# program to find sum of // product of every number and // square of its frequency in // the given range using System; using System.Collections.Generic; class GFG{ // Function to solve queries public static void answerQueries( int [] arr, int n, int [,] queries) { for ( int i = 0; i < queries.GetLength(0); i++) { // Calculating answer // for every query int ans = 0; // The end points // of the ith query int l = queries[i, 0] - 1; int r = queries[i, 1] - 1; // Hashmap for storing frequency Dictionary< int , int > freq = new Dictionary< int , int >(); for ( int j = l; j < r+ 1; j++) { // Iterating over the given // subarray and storing // frequency in a map // Incrementing the frequency freq[arr[j]] = freq.GetValueOrDefault(arr[j], 0) + 1; } foreach ( int k in freq.Keys) { // Adding the contribution // of ith number ans += k * freq[k]; } // Print answer Console.WriteLine(ans); } } // Driver code static public void Main() { int [] arr = { 1, 2, 1 }; int n = arr.Length; int [,] queries = { { 1, 2 }, { 1, 3 } }; // Calling function answerQueries(arr, n, queries); } } // This code is contributed by avanitrachhadiya2155 |
Javascript
<script> // Javascript implementation to find // sum of product of every number // and square of its frequency // in the given range // Function to solve queries function answerQueries(arr, n, queries) { for ( var i = 0; i < queries.length; i++) { // Calculating answer // for every query var ans = 0; // The end points // of the ith query var l = queries[i][0] - 1; var r = queries[i][1] - 1; // map for storing frequency var freq = new Map(); for ( var j = l; j <= r; j++) { // Iterating over the given // subarray and storing // frequency in a map // Incrementing the frequency if (freq.has(arr[j])) freq.set(arr[j], freq.get(arr[j]) + 1) else freq.set(arr[j], 1) } // Iterating over map to find answer freq.forEach((value, key) => { // Adding the contribution // of ith number ans += (key * value); }); // Print answer document.write(ans + "<br>" ); } } // Driver code var arr = [ 1, 2, 1 ]; var n = arr.length; var queries = [ [ 1, 2 ], [ 1, 3 ] ]; answerQueries(arr, n, queries); // This code is contributed by itsok </script> |
3 4
Time Complexity: O(Q * N)
Auxiliary Space Complexity: O(N)
Efficient Approach:
To optimize the above method we will try to implement the problem using Mo’s Algorithm.
- Sort the queries first according to their block of
size using custom comparator and also store the indexes of each query in a map for printing in order.
- Now, we will maintain two-pointer L and R which we iterate over the array for answering the queries. As we move the pointers, if we are adding some number in our range, we’ll first remove the contribution of its previous freq from the answer, then increment the frequency and finally add the contribution of new frequency in answer.
- And if we remove some element from the range, we’ll do the same, remove the contribution of existing freq of this number, decrement the freq, add the contribution of its new frequency.
Below is the implementation of the above approach:
C++
// C++ implementation to find sum // of product of every number // and square of its frequency // in the given range #include <bits/stdc++.h> using namespace std; // Stores frequency const int N = 1e5 + 5; // Frequency array vector< int > freq(N); int sq; // Function for comparator bool comparator( pair< int , int >& a, pair< int , int >& b) { // comparator for sorting // according to the which query // lies in the which block; if (a.first / sq != b.first / sq) return a.first < b.first; // if same block, // return which query end first return a.second < b.second; } // Function to add numbers in range void add( int x, int & ans, int arr[]) { // removing contribution of // old frequency from answer ans -= arr[x] * freq[arr[x]]; // incrementing the frequency freq[arr[x]]++; // adding contribution of // new frequency to answer ans += arr[x] * freq[arr[x]]; } void remove ( int x, int & ans, int arr[]) { // removing contribution of // old frequency from answer ans -= arr[x] * freq[arr[x]]; // Decrement the frequency freq[arr[x]]--; // adding contribution of // new frequency to answer ans += arr[x] * freq[arr[x]]; } // Function to answer the queries void answerQueries( int arr[], int n, vector<pair< int , int > >& queries) { sq = sqrt (n) + 1; vector< int > answer( int (queries.size())); // map for storing the // index of each query map<pair< int , int >, int > idx; // Store the index of queries for ( int i = 0; i < queries.size(); i++) idx[queries[i]] = i; // Sort the queries sort(queries.begin(), queries.end(), comparator); int ans = 0; // pointers for iterating // over the array int x = 0, y = -1; for ( auto & i : queries) { // iterating over all // the queries int l = i.first - 1, r = i.second - 1; int id = idx[i]; while (x > l) { // decrementing the left // pointer and adding the // xth number's contribution x--; add(x, ans, arr); } while (y < r) { // incrementing the right // pointer and adding the // yth number's contribution y++; add(y, ans, arr); } while (x < l) { // incrementing the left pointer // and removing the // xth number's contribution remove (x, ans, arr); x++; } while (y > r) { // decrementing the right // pointer and removing the // yth number's contribution remove (y, ans, arr); y--; } answer[id] = ans; } // printing the answer of queries for ( int i = 0; i < queries.size(); i++) cout << answer[i] << endl; } // Driver Code int main() { int arr[] = { 1, 1, 2, 2, 1, 3, 1, 1 }; int n = sizeof (arr) / sizeof (arr[0]); vector<pair< int , int > > queries = { { 2, 7 }, { 1, 6 } }; answerQueries(arr, n, queries); } |
Java
/*package whatever //do not write package name here */ import java.util.*; public class GFG { static class Pair{ int key; int value; public Pair( int k, int v){ key = k; value = v; } } // Stores frequency static int N = ( int )1e5 + 5 ; // Frequency array static int freq[] = new int [N]; static int sq = 0 ; static int ans = 0 ; // Function to add numbers in range static void add( int x, int arr[]) { // removing contribution of // old frequency from answer ans -= arr[x] * freq[arr[x]]; // incrementing the frequency freq[arr[x]]++; // adding contribution of // new frequency to answer ans += arr[x] * freq[arr[x]]; } static void remove( int x, int arr[]) { // removing contribution of // old frequency from answer ans -= arr[x] * freq[arr[x]]; // Decrement the frequency freq[arr[x]]--; // adding contribution of // new frequency to answer ans += arr[x] * freq[arr[x]]; } // Function to answer the queries static void answerQueries( int arr[], int n, ArrayList<Pair> queries) { sq = ( int )Math.sqrt(n) + 1 ; int [] answer = new int [queries.size()]; // map for storing the // index of each query Map<Pair, Integer> idx = new HashMap<>(); // Store the index of queries for ( int i = 0 ; i < queries.size(); i++) idx.put(queries.get(i),i); // Sort the queries Collections.sort(queries,(a,b)->{ if (a.key/sq != b.key/sq) return a.key-b.key; return a.value - b.value; }); ans = 0 ; // pointers for iterating // over the array int x = 0 , y = - 1 ; for (Pair i : queries) { // iterating over all // the queries int l = i.key - 1 , r = i.value - 1 ; int id = idx.get(i); while (x > l) { // decrementing the left // pointer and adding the // xth number's contribution x--; add(x, arr); } while (y < r) { // incrementing the right // pointer and adding the // yth number's contribution y++; add(y, arr); } while (x < l) { // incrementing the left pointer // and removing the // xth number's contribution remove(x, arr); x++; } while (y > r) { // decrementing the right // pointer and removing the // yth number's contribution remove(y, arr); y--; } answer[id] = ans; } // printing the answer of queries for ( int i = 0 ; i < queries.size(); i++) System.out.println(answer[i]); } public static void main (String[] args) { int arr[] = new int []{ 1 , 1 , 2 , 2 , 1 , 3 , 1 , 1 }; int n = arr.length; ArrayList<Pair> queries = new ArrayList<>(); queries.add( new Pair( 2 , 7 )); queries.add( new Pair( 1 , 6 )); answerQueries(arr, n, queries); } } // This code is contributed by aadityaburujwale. |
Python3
# Python3 implementation to find sum # of product of every number # and square of its frequency # in the given range import functools # Stores frequency N = 10 * * 5 + 5 ; # Frequency array freq = [ 0 for _ in range (N)] sq = 0 ; # Function for comparator def comparator(a, b): # comparator for sorting # according to the which query # lies in the which block; if (a[ 0 ] / sq ! = b[ 0 ] / sq): return a[ 0 ] > b[ 0 ]; # if same block, # return which query end first return a[ 1 ] > b[ 1 ]; # Function to add numbers in range def add(x, ans, arr): # removing contribution of # old frequency from answer ans - = arr[x] * freq[arr[x]]; # incrementing the frequency freq[arr[x]] + = 1 ; # adding contribution of # new frequency to answer ans + = arr[x] * freq[arr[x]]; return ans; def remove(x, ans, arr): # removing contribution of # old frequency from answer ans - = arr[x] * freq[arr[x]]; # Decrement the frequency freq[arr[x]] - = 1 ; # adding contribution of # new frequency to answer ans + = arr[x] * freq[arr[x]]; return ans; # Function to answer the queries def answerQueries(arr, n, queries): global sq sq = n * * 0.5 + 1 ; answer = [ 0 for _ in range ( len (queries))] # map for storing the # index of each query idx = {}; # Store the index of queries for i in range ( len (queries)): x = (queries[i][ 0 ], queries[i][ 1 ]); idx[x] = i; # Sort the queries queries.sort( key = functools.cmp_to_key(comparator)); ans = 0 ; # pointers for iterating # over the array x = 0 y = - 1 ; for i in queries: # iterating over all # the queries l = i[ 0 ] - 1 r = i[ 1 ] - 1 ; if (i[ 0 ], i[ 1 ]) not in idx: idx[(i[ 0 ], i[ 1 ])] = 0 ; id1 = (idx[i[ 0 ], i[ 1 ]]); while (x > l) : # decrementing the left # pointer and adding the # xth number's contribution x - = 1 ; ans = add(x, ans, arr); while (y < r) : # incrementing the right # pointer and adding the # yth number's contribution y + = 1 ; ans = add(y, ans, arr); while (x < l) : # incrementing the left pointer # and removing the # xth number's contribution ans = remove(x, ans, arr); x + = 1 ; while (y > r) : # decrementing the right # pointer and removing the # yth number's contribution ans = remove(y, ans, arr); y - = 1 ; answer[id1] = ans; # printing the answer of queries for i in range ( len (queries)): print (answer[i]); # Driver Code arr = [ 1 , 1 , 2 , 2 , 1 , 3 , 1 , 1 ]; n = len (arr); queries = [[ 2 , 7 ], [ 1 , 6 ] ]; answerQueries(arr, n, queries); # This code is contributed by phasing17. |
C#
using System; using System.Collections.Generic; namespace GFG { class Program { // Stores frequency static int N = ( int )1e5 + 5; // Frequency array static int [] freq = new int [N]; static int sq = 0; static int ans = 0; // Function to add numbers in range static void Add( int x, int [] arr) { // removing contribution of // old frequency from answer ans -= arr[x] * freq[arr[x]]; // incrementing the frequency freq[arr[x]]++; // adding contribution of // new frequency to answer ans += arr[x] * freq[arr[x]]; } static void Remove( int x, int [] arr) { // removing contribution of // old frequency from answer ans -= arr[x] * freq[arr[x]]; // Decrement the frequency freq[arr[x]]--; // adding contribution of // new frequency to answer ans += arr[x] * freq[arr[x]]; } // Function to answer the queries static void AnswerQueries( int [] arr, int n, List<( int , int )> queries) { sq = ( int )Math.Sqrt(n) + 1; int [] answer = new int [queries.Count]; // map for storing the // index of each query Dictionary<( int , int ), int > idx = new Dictionary<( int , int ), int >(); // Store the index of queries for ( int i = 0; i < queries.Count; i++) { idx[queries[i]] = i; } // Sort the queries queries.Sort((a, b) => { if (a.Item1 / sq != b.Item1 / sq) { return a.Item1 - b.Item1; } return a.Item2 - b.Item2; }); ans = 0; // pointers for iterating // over the array int x = 0, y = -1; foreach (( int , int )i in queries) { // iterating over all // the queries int l = i.Item1 - 1, r = i.Item2 - 1; int id = idx[i]; while (x > l) { // decrementing the left // pointer and adding the // xth number's contribution x--; Add(x, arr); } while (y < r) { // incrementing the right // pointer and adding the // yth number's contribution y++; Add(y, arr); } while (x < l) { // incrementing the left pointer // and removing the // xth number's contribution Remove(x, arr); x++; } while (y > r) { // decrementing the right // pointer and removing the // yth number's contribution Remove(y, arr); y--; } answer[id] = ans; } // printing the answer of queries foreach ( int i in answer) { Console.WriteLine(i); } } // Driver Code static void Main( string [] args) { int [] arr = new int [] { 1, 1, 2, 2, 1, 3, 1, 1 }; int n = arr.Length; List<( int , int )> queries = new List<( int , int )>(); queries.Add((2, 7)); queries.Add((1, 6)); AnswerQueries(arr, n, queries); } } } // This code is contributed by phasing17. |
Javascript
// JS implementation to find sum // of product of every number // and square of its frequency // in the given range // Stores frequency let N = 1e5 + 5; // Frequency array let freq = new Array(N).fill(0); let sq; // Function for comparator function comparator(a, b) { // comparator for sorting // according to the which query // lies in the which block; if (a[0] / sq != b[0] / sq) return a[0] > b[0]; // if same block, // return which query end first return a[1] > b[1]; } // Function to add numbers in range function add(x, ans, arr) { // removing contribution of // old frequency from answer ans -= arr[x] * freq[arr[x]]; // incrementing the frequency freq[arr[x]]++; // adding contribution of // new frequency to answer ans += arr[x] * freq[arr[x]]; return ans; } function remove(x, ans, arr) { // removing contribution of // old frequency from answer ans -= arr[x] * freq[arr[x]]; // Decrement the frequency freq[arr[x]]--; // adding contribution of // new frequency to answer ans += arr[x] * freq[arr[x]]; return ans; } // Function to answer the queries function answerQueries(arr, n, queries) { sq = Math.sqrt(n) + 1; let answer = new Array(queries.length).fill(0); // map for storing the // index of each query let idx = {}; // Store the index of queries for ( var i = 0; i < queries.length; i++) { let x = queries[i][0] + "#" + queries[i][1]; idx[x] = i; } // Sort the queries queries.sort(comparator); let ans = 0; // pointers for iterating // over the array let x = 0, y = -1; for (let i of queries) { // iterating over all // the queries let l = i[0] - 1, r = i[1] - 1; if (!idx.hasOwnProperty(i[0] + "#" + i[1])) idx[i[0] + "#" + i[1]] = 0; let id = idx[i[0] + "#" + i[1]]; while (x > l) { // decrementing the left // pointer and adding the // xth number's contribution x--; ans = add(x, ans, arr); } while (y < r) { // incrementing the right // pointer and adding the // yth number's contribution y++; ans = add(y, ans, arr); } while (x < l) { // incrementing the left pointer // and removing the // xth number's contribution ans = remove(x, ans, arr); x++; } while (y > r) { // decrementing the right // pointer and removing the // yth number's contribution ans = remove(y, ans, arr); y--; } answer[id] = ans; } // printing the answer of queries for ( var i = 0; i < queries.length; i++) console.log(answer[i]); } // Driver Code let arr = [ 1, 1, 2, 2, 1, 3, 1, 1 ]; let n = arr.length; let queries = [[2, 7 ], [ 1, 6 ] ]; answerQueries(arr, n, queries); |
10 10
Time Complexity: O(N * sqrt{N})
Auxiliary Space Complexity: O(N)
Please Login to comment...