给定范围内的数组元素计数,当 Q 查询除以 K 时余数为 X
给定一个大小为N的数组arr[] ,一个整数K和Q查询,每个查询的形式为{x, l, r} 。对于每个查询,任务是查找索引范围[l, r]中除以K时余数为x的所有元素的计数。
例子:
Input: arr[] = {15, 28, 72, 43, 20, 0, 97}, K = 5, queries[] = {{3, 0, 3}, {0, 0, 6}, {6, 2, 4}}
Output: 2, 3, 0
Explanation: For the first query, there are 2 elements in the range [0, 3] whose remainder is 3 (28, 43).
Similarly 3 elements in range [0, 6] whose remainder is 0 (15, 20, 0).
In the third query, elements whose remainder are 6 should be found.
But for the given K = 5 possible remainders are only [0, 4]. So for any x >= K, answer will be 0.
Input: arr[] = {2, 4, 6, 7, 5}, K = 3, queries[] = {{2, 1, 4}}
Output: 1
方法 1:一种简单的方法是,对于每个查询,遍历l 到 r并计算余数为x的所有元素。
时间复杂度: O(N * Q)
辅助空间: O(1)
方法二:这个问题也可以通过基于以下思路的预计算来解决:
Precalculate what will be the remainder, when arr[i] is divided by K and store them in a matrix (say mat[]) where mat[i][j] represents the remainder of arr[j] is i when divided by K.
Now prefix sum of ith row of the matrix gives the count of elements which will have remainder i when divided by K. Therefore, after prefix sum mat[i][j] will represent total count of elements till jth index having remainder i when divided by K.
So for a query {x, l, r} the answer will be (mat[x][r] – mat[x][l] [+1 if arr[l]%K is x])
请按照下图更好地理解矩阵的构造。
插图:
Consider arr[] = {15, 28, 72, 43, 20, 0, 97}, K = 5
Make a 2D matrix named precompute, of size (K*N), and initialize it with 0.
For the ith element, mark precompute[arr[i]%K][i] = 1, do this for all i which states that the ith element has remainder arr[i]%K.
For the given example our precompute matrix will look like the following where row: remainder, column: index num. 0 1 2 3 4 5 6 0 1 0 0 0 1 1 0 1 0 0 0 0 0 0 0 2 0 0 1 0 0 0 1 3 0 1 0 1 0 0 0 4 0 0 0 0 0 0 0
Then for each row calculate prefix sum. Now matrix will look like this: 0 1 2 3 4 5 6 0 1 1 1 1 2 3 3 1 0 0 0 0 0 0 0 2 0 0 1 1 1 1 2 3 0 1 1 2 2 2 2 4 0 0 0 0 0 0 0
Here precompute[0][6] denotes that till 6th index there are a total of 3 elements which will have reaminder 3 when divided by 5.
按照下面提到的步骤来实现这个想法:
- 创建二维数组(比如precompute )。
- 如上所述构造数组。
- 遍历查询:
- 对于每个查询,根据上面显示的公式计算元素的数量并将其存储在答案数组中。
- 返回有答案的数组。
注意:此方法仅在查询数大于K时更有效。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
const int MXN = 2e5;
int precompute[100][MXN];
// To precompute count prefix sum of all
// possible remainders
void precomputation(int arr[], int n, int k)
{
// Mark cell whose remainder is arr[i]%k
for (int i = 0; i < n; i++)
precompute[arr[i] % k][i] = 1;
// Take prefix sum for all rows
for (int i = 0; i < k; i++) {
for (int j = 1; j < n; j++) {
precompute[i][j]
+= precompute[i][j - 1];
}
}
}
// Function to find the
// count of numbers for the queries
vector findCount(int arr[], int K, int N,
vector >& queries)
{
vector res;
// Intialise matrix with 0
memset(precompute, 0, sizeof precompute);
// To calculate count of reaminders
precomputation(arr, N, K);
for (int i = 0; i < queries.size(); i++) {
int x = queries[i][0];
int l = queries[i][1];
int r = queries[i][2];
if (x >= K) {
res.push_back(0);
continue;
}
int count = precompute[x][r]
- precompute[x][l]
+ (arr[l] % K == x);
res.push_back(count);
}
return res;
}
// Driver code
int main()
{
int arr[] = { 15, 28, 72, 43, 20, 0, 97 };
int K = 5;
int N = sizeof(arr) / sizeof(arr[0]);
vector > queries{ { 3, 0, 3 },
{ 0, 0, 6 },
{ 6, 2, 4 } };
vector ans
= findCount(arr, K, N, queries);
for (int x : ans)
cout << x << " ";
return 0;
}
Python3
# python3 program for the above approach
MXN = int(2e5)
precompute = [[0 for _ in range(MXN)] for _ in range(100)]
# To precompute count prefix sum of all
# possible remainders
def precomputation(arr, n, k):
global precompute
# Mark cell whose remainder is arr[i]%k
for i in range(0, n):
precompute[arr[i] % k][i] = 1
# Take prefix sum for all rows
for i in range(0, k):
for j in range(1, n):
precompute[i][j] += precompute[i][j - 1]
# Function to find the
# count of numbers for the queries
def findCount(arr, K, N, queries):
global precompute
res = []
# Intialise matrix with 0
# To calculate count of reaminders
precomputation(arr, N, K)
for i in range(0, len(queries)):
x = queries[i][0]
l = queries[i][1]
r = queries[i][2]
if (x >= K):
res.append(0)
continue
count = precompute[x][r] - precompute[x][l] + (arr[l] % K == x)
res.append(count)
return res
# Driver code
if __name__ == "__main__":
arr = [15, 28, 72, 43, 20, 0, 97]
K = 5
N = len(arr)
queries = [[3, 0, 3],
[0, 0, 6],
[6, 2, 4]]
ans = findCount(arr, K, N, queries)
for x in ans:
print(x, end=" ")
# This code is contributed by rakeshsahni
Javascript
Java
// Java program for the above approach
import java.io.*;
import java.util.ArrayList;
class GFG {
static int MXN = 200000;
static int[][] precompute = new int[100][MXN];
// To precompute count prefix sum of all
// possible remainders
static void precomputation(int[] arr, int n, int k)
{
// Mark cell whose remainder is arr[i]%k
for (int i = 0; i < n; i++)
precompute[arr[i] % k][i] = 1;
// Take prefix sum for all rows
for (int i = 0; i < k; i++) {
for (int j = 1; j < n; j++) {
precompute[i][j] += precompute[i][j - 1];
}
}
}
// Function to find the
// count of numbers for the queries
static ArrayList
findCount(int[] arr, int K, int N, int[][] queries)
{
ArrayList res = new ArrayList();
// Intialise matrix with 0
for (int i = 0; i < 100; i++) {
for (int j = 0; j < MXN; j++)
precompute[i][j] = 0;
}
// To calculate count of reaminders
precomputation(arr, N, K);
for (int i = 0; i < queries.length; i++) {
int x = queries[i][0];
int l = queries[i][1];
int r = queries[i][2];
if (x >= K) {
res.add(0);
continue;
}
int count = precompute[x][r] - precompute[x][l]
+ ((arr[l] % K == x) ? 1 : 0);
res.add(count);
}
return res;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 15, 28, 72, 43, 20, 0, 97 };
int K = 5;
int N = arr.length;
int[][] queries
= { { 3, 0, 3 }, { 0, 0, 6 }, { 6, 2, 4 } };
ArrayList ans
= findCount(arr, K, N, queries);
for (int i = 0; i < ans.size(); i++)
System.out.print(ans.get(i) + " ");
}
}
//thise code was contributed by phasing17
2 3 0
时间复杂度: O(Q + K*N)
辅助空间: O(K*N)