前几天我遇到了与查询相关的问题,但我无法解决。
给定具有 N 整数和正整数 M 的数组,您必须回答 Q 查询。每个查询的特征为( i , j ),其中 i 和 j 是数组的每个索引。在每个查询中,您必须回答存在多少对( r , s ),以便
限制:
N <= 50,000
Q <= 50,000
M <= 100
我有一个动态编程解决方案,可以预处理O( N ^ 2)中的每个查询( r , s ),但这是不够快。有更有效的解决方案吗?我对Mo的算法或段树有一些想法,但我无法得到它。
答案 0 :(得分:3)
计算每个i = 1..N
的原始数组的前缀总和(假设它基于1)。
任何两个索引Sum[r]
和Sum[s]
的{{1}}和r
的等效性,其中s
表示索引位于{{1}的数组元素的总和可以被r < s
整除(我们需要计算区间内这种等价的数量)。此步骤的时间复杂度为[r+1, s]
。
为每个M
预先计算数组O(N)
:
Count
存储i = 1..N, j = 0..M-1
(Count[i][j]
)等于Sum[len]
的次数。此步骤的时间复杂度为len <= i
。
对于每个查询j
,答案将等于:
对于余数O(N*M)
的每个可能值,我们找到(i, j)
- k
在D(k)
区间内等于Sum[len]
的次数。然后,我们向结果中添加k
个[i, j]
区间边界的所有可能对的数量D(k)
。时间复杂度:每个查询D(k)*(D(k)-1)/2
。
复杂性:O(M)
,对于给定的约束条件就可以了。
答案 1 :(得分:1)
首先请注意,对于任何总和为(r, s)
倍数的子阵列M
:
sum(r, s) == sum(i, s) - sum(i, r - 1)
== (qa * M + ra) - (qb * M + rb)
其中ra
和rb
都小于M
且大于或等于0
(即除以后的相应余数M
)。
现在sum(r, s)
可以被M
整除,因此在除以0
之后,其余为M
。因此:
ra == rb
如果我们在将子数组(i, i)
,(i, i + 1)
,...,(i, j)
除以M
作为r1
之后,将所有余数计算出来,{ {1}},...,r2
然后将所有这些的计数存储在大小为rj
的数组R
中,以便M
为剩余数量等于R[k]
,然后:
k
并且对于每个R[0] == the number of subarrays starting at i that are divisible by M
和k >= 0
,k < M
我们可以计算R[k] > 1
选择R[k]
:
2
不从(R[k] * (R[k] - 1)) / 2
开始且可被{{1}}整除的子阵列。
创建和求和所有这些值为我们提供了每个i
查询的O(N + M)答案。