【问题标题】:Efficent Algorithm to Answer Subarray Queries fast快速回答子数组查询的高效算法
【发布时间】:2017-08-01 23:59:50
【问题描述】:

前几天遇到了一个查询相关的问题,但是解决不了。

给定一个包含 N 个整数和一个正整数 M 的数组,您必须回答 Q 个查询。每个查询的特征是 ( i , j ),其中 ij 是数组的每个索引。在每个查询中,您必须回答存在多少对( rs )使得

  1. i r s j
  2. 索引在 [ r , s ] 中的数组元素之和可被 M 整除。

限制:

N <= 50,000
Q <= 50,000
M <= 100

我有一个动态编程解决方案,可以预处理 O( N^2 ) 中的每个查询( rs ),但那是不够快。有没有更有效的解决方案?我对 Mo 的算法或分段树有一些想法,但我无法得到它。

【问题讨论】:

  • 先对数组进行排序(对数复杂度)。现在可以通过二分搜索找到子范围 (i,j)。要计算给定的 (i,j),请预先计算范围模数 M 中的所有值,以及每个值 [0,M) 出现的次数。根据每个的计数,可以简单地计算可能的对数。
  • @SamVarshavchik, (i, j) 是数组的索引,而不是值。

标签: c++ algorithm


【解决方案1】:
  1. 计算每个 i = 1..N 的原始数组的前缀总和(假设它是从 1 开始的)。

    Sum[r]Sum[s] 对于任意两个索引 rs 的等价性,其中 r &lt; s 意味着具有 [r+1, s] 中的索引的数组元素的总和可以被 M 整除(我们需要计算区间内等价的数量)。这一步的时间复杂度为O(N)

  2. 为每个 i = 1..N, j = 0..M-1 预先计算数组 Count
    Count[i][j] 存储Sum[len](其中len &lt;= i)等于j 的次数。这一步的时间复杂度是O(N*M)

  3. 对于每个查询(i, j),答案将等于:
    对于余数k 的每个可能值,我们发现D(k) - 在区间[i, j]Sum[len] 等于k 的次数。然后我们将所有可能的D(k) 区间边界对的数量添加到结果中,即D(k)*(D(k)-1)/2。时间复杂度:O(M) 用于每个查询。

复杂性O(N) + O(N*M) + O(Q*M) = O((Q+N)*M),对于给定的约束条件是可以的。

【讨论】:

    【解决方案2】:

    首先请注意,对于任何子数组 (r, s),其总和为 M 的倍数:

    sum(r, s) == sum(i, s) - sum(i, r - 1)
    
              == (qa * M + ra) - (qb * M + rb)
    

    其中rarb 都小于M 并且大于或等于0分别除以M 后的余数)。

    现在sum(r, s) 可以被M 整除,所以除以M 后的余数是0。因此:

    ra == rb
    

    如果我们在将子数组(i, i)(i, i + 1)、...、(i, j) 除以M 之后计算所有余数,则为r1r2、...、rj然后将所有这些的计数存储在大小为M 的数组R 中,以便R[k] 是等于k 的余数,然后:

    R[0] == the number of subarrays starting at i that are divisible by M
    

    对于每个k &gt;= 0k &lt; M 这样R[k] &gt; 1 我们可以计算R[k] 选择2

    (R[k] * (R[k] - 1)) / 2
    

    不以i 开始的子数组可以被M 整除。

    创建和汇总所有这些值可以为每个 (r, s) 查询提供 O( N + M ) 的答案。

    【讨论】:

    • 为什么复杂度是O(Q+M)?可能是O(Q*M)
    • @DAle 从ij 循环需要Q 步,计算运行总和的下一个累加,该点的余数,并更新R。然后 M 步循环遍历R 在每一步更新总数为 O( Q + M )
    • Q 是查询次数。
    • @DAle 啊,你完全正确!更新的答案 - 谢谢。 OP 每个查询都有 O( N^2 ) - 这是每个查询 O ( N + M )。
    猜你喜欢
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-01
    • 2019-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多