如何实现累积产品表?

时间:2016-08-20 01:26:21

标签: algorithm cumulative-frequency

鉴于以下问题:

有一个k整数序列,名为 s ,可以有2个操作,

1) Sum [i,j] - s [i] + s [i + 1] + ... + s [j] 的价值是多少?

2)更新[i,val] - 将 s [i] 的值更改为 val

我相信这里的大多数人都听说过使用累积频率表/ fenwick树来优化复杂性。

现在,如果我不想查询总和,而是想要执行以下操作:

产品[i,j] - s [i] * s [i + 1] * ... * s [j] 的价值是多少?

新问题起初似乎微不足道,至少对于第一次操作 Product [i,j]

假设我使用名为 f 的累积产品表:

  1. 首先想到的是,当我们调用 Update [i,val] 时,我们应该将 f [z] 的累积产品除以来自i的 z - > j s [i] 的旧值再乘以新值。
  2. 但如果 s [i] 的旧值为0,我们将面临2个问题:

    • 除以0.但是通过检查s [i]的旧值是否为0可以很容易地解决这个问题。

    • 任何实数为0的乘积为0.此结果将导致 f [i] f [j] 的所有其他值0.所以我们无法成功执行 Update [i,val] 。除了 f [i] 之外,这个问题不会影响其他值。

  3. 有没有人有任何想法如何实现支持上述2项操作的累积产品表?

1 个答案:

答案 0 :(得分:2)

维护2个表:

  • 累积产品表,其中所有零条目都已存储为1(以避免影响其他条目)。
  • 存储零个条目数的累积和。如果f [i]为0则每个条目s [i]为1,如果非零则为0。

要计算累积乘积,首先计算给定范围内零个条目的累积和。如果非零(即在该范围内存在1或更多的零)则累积乘积为零。如果为零,则按照您的描述计算累积产品。

将您的因子作为对数存储在某些基数中可能更准确,并将累积乘积计算为对数值的总和。你只需计算2个累积金额。在这种情况下,您需要在产品表中存储零条目,因为日志值为0(即值为1)。

这是一个例子,使用简单的累积总和(不是Fenwick树,但你可以轻松地使用它们):

 row   f   cum_f   isZero  cum_isZero  log(f)  cum_log(f)

-1     1     1       0         0        0         0

 0     3     3       0         0        0.477     0.477
 1     0     3       1         1        -inf      0.477
 2     4    12       0         1        0.602     1.079
 3     2    24       0         1        0.301     1.38
 4     3    72       0         1        0.477     1.857

row是索引,f是因子,cum_f是f处理零的累积乘积,好像它们是1,isZero是一个标志,表示f是否为零,cum_isZero是isZero标志的累积和,log (f)是基数为10的f的对数,cum_log(f)是log_f的累积和,将-inf视为零。

要计算从第i行到第j行(包括)的范围的和或乘积,从行[j]中减去行[i-1],使用第-1行作为"虚拟"行。

要计算行0-2中f的累积乘积,首先找到isZero的累积和:cum_isZero [2] - cum_isZero [-1] = 1 - 0 = 1.这是非零的,所以累积产品是0

要计算第2-4行中f的累积乘积,请执行以下操作:cum_isZero [4] - cum_isZero [1] = 0 - 0 = 0.这是零,因此我们可以计算产品。

使用cum_f:cum_f [4] / cum_f [1] = 72/3 = 24 = 4 x 2 x 3

使用cum_log_f:cum_log(f)[4] - cum_log(f)[1] = 1.857 - 0.477 = 1.38

10 1.38 =约24