我会假设你的查询操作是在范围[L, R]
中找到总和。
你肯定希望以高效的方式完成此操作,可能每个操作都是O(log n)
。
你需要一种方法来存储数据在lazy
字段中,以便在遍历树进行查询时计算更新。
让我们看看能否以更好的方式编写更新:
v = 1 - (1 - v) * a
= 1 - (a - av)
= 1 - a + av
如果我们这样做两次:
1 - a + av = 1 - (1 - [1 - a + av]) * a
= 1 - (a - a + a**2 - a**2 v)
= 1 - a + a - a**2 + a**2 v
= 1 - a**2 + a**2 v
相当于(应用于整个范围):
a
a
1
更新懒惰字段时,明显只需增加 a
的指数。
您可以像链接的懒惰传播文章中描述的那样懒惰地执行这 3 个操作。
因此,您的更新操作可以分为 3 个懒惰更新,在 O(log n)
时间内完成,总时间为 O(log n)
。
a[l] = x
,a[l+1] = x
,...
,a[r-1] = x
,a[r] = x
。可以将整个子树的此操作仅存储为值x
,这意味着该操作是将x
分配给此子树的每个顶点。对于顶点v
中的惰性传播,我们只需将其应用于顶点v
的直接子代,并在那里存储相同的惰性操作x
。请注意,子代中的任何旧惰性操作都会被分配擦除。这就是分配的性质。arr[i] = (1 - (1 - arr[i]) * a)
,让我们看看在常数a
和b
下进行两次此类操作后值如何更改。v
。w = 1 - (1 - v) * a
,即a*v + (1-a)*1
。1 - (1 - w) * b
,即b*w + (1-b)*1
,这又是b*a*v + b*(1-a)*1 + (1-b)*1
,最终变成(b*a)*v + (1-b*a)*1
。(我可能混淆了加号和减号,但这不会改变整个图像。)b*a
和1-b*a
。int
、double
或其他)的容量。如果该问题涉及模某个整数的整数余数而不仅仅是整数或实数,则这不是问题;否则,存储系数很快就会成为问题。