鉴于以下问题:
有一个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 的累积产品表:
但如果 s [i] 的旧值为0,我们将面临2个问题:
除以0.但是通过检查s [i]的旧值是否为0可以很容易地解决这个问题。
任何实数为0的乘积为0.此结果将导致 f [i] 到 f [j] 的所有其他值0.所以我们无法成功执行 Update [i,val] 。除了 f [i] 之外,这个问题不会影响其他值。
有没有人有任何想法如何实现支持上述2项操作的累积产品表?
答案 0 :(得分:2)
维护2个表:
要计算累积乘积,首先计算给定范围内零个条目的累积和。如果非零(即在该范围内存在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