给定一个整数数组arr []和一个查询数组,任务是查找给定范围[L,R]中每个数字的乘积和其频率的和,其中每个范围在查询数组中给出。
例子:
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) = 4
Input: 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
天真的方法:
为了解决上述问题,天真的方法是遍历查询中给定的子数组。为子数组中每个数字的频率维护一个映射,并在映射上进行迭代并计算答案。
下面是上述方法的实现:
C++
// C++ implementation to find
// sum of product of every number
// and square of its frequency
// in the given range
#include
using namespace std;
// Function to solve queries
void answerQueries(
int arr[], int n,
vector >& 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 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 > 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 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 freq = new Dictionary();
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
C++
// C++ implementation to find sum
// of product of every number
// and square of its frequency
// in the given range
#include
using namespace std;
// Stores frequency
const int N = 1e5 + 5;
// Frequnecy array
vector freq(N);
int sq;
// Function for comparator
bool comparator(
pair& a,
pair& b)
{
// comparator for sorting
// accoring to the which query
// lies in the whcih 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 >& queries)
{
sq = sqrt(n) + 1;
vector answer(
int(queries.size()));
// map for storing the
// index of each query
map, 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 > queries
= { { 2, 7 },
{ 1, 6 } };
answerQueries(arr, n, queries);
}
3
4
时间复杂度: O(Q * N)
辅助空间复杂度: O(N)
高效方法:
为了优化上述方法,我们将尝试使用Mo’s算法来实现该问题。
- 首先根据查询的块对查询进行排序使用自定义比较器调整大小,并将每个查询的索引存储在映射中以按顺序打印。
- 现在,我们将维护两个指针L和R,它们遍历数组以回答查询。当我们移动指针时,如果我们要在范围内添加一些数字,我们将首先从答案中删除其前一个频率的贡献,然后增加频率,最后在答案中添加新频率的贡献。
- 如果我们从范围中删除某些元素,我们将做同样的事情,删除此数字现有频率的贡献,减少频率,添加其新频率的贡献。
下面是上述方法的实现:
C++
// C++ implementation to find sum
// of product of every number
// and square of its frequency
// in the given range
#include
using namespace std;
// Stores frequency
const int N = 1e5 + 5;
// Frequnecy array
vector freq(N);
int sq;
// Function for comparator
bool comparator(
pair& a,
pair& b)
{
// comparator for sorting
// accoring to the which query
// lies in the whcih 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 >& queries)
{
sq = sqrt(n) + 1;
vector answer(
int(queries.size()));
// map for storing the
// index of each query
map, 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 > queries
= { { 2, 7 },
{ 1, 6 } };
answerQueries(arr, n, queries);
}
10
10
时间复杂度: O(N * sqrt {N})
辅助空间复杂度: O(N)