我一直在思考以下问题:
我们给了一个 n 个数字数组。我们从第一个索引开始,我们的任务是到达最后一个索引。我们的每一步都可以向前跳一两步,而索引上的数字代表我们访问该索引所需支付的费用。我们需要找到最便宜的到达数组末尾的方法。
例如,如果数组如下所示: [2,1,4,2,5] 最便宜的到达终点的方法是10:我们访问索引 1- > 2-> 4-> 5 ,我们必须支付 2 + 1 + 2 + 5 = 10 ,这是最便宜的方式。假设 f(i)是获得索引 i 的最便宜价格。我们可以通过实现 f(i)= arr [i] + min(f(i-1),f(i- 2))
但是这里有一个转折点: 数组会更新几次,每次更新后,我们都需要能够在 O(logn)时间中告诉您目前最便宜的方法是什么。通过告诉索引将要更改的索引和将要更改的编号来更新数组。例如,更新可能是 arr [2] = 7 ,将我们的示例数组更改为 [2,7,4,2,5] 。现在最便宜的方法是11。
现在我们如何在 O(logn)时间内支持这些更新?有什么想法吗?
这是我到目前为止提出的: 首先,我将为动态编程创建数组 f ,如前所述。我将通过以下方式将该数组的内容存储在段树 s 中: s(i)= f(i)-f(i-1)。这将允许我在 O(logn)时间内更新 f 的时间间隔(向每个值添加一个常数),并在 O(登录)时间。这很方便,因为在进行一些更新后,经常会发生 f 中的所有值都需要在 f 中的给定索引之后增加一个常数的情况。因此,通过在每次更新后在细分树中询问 s(n)的值,我们将获得所需的答案。
但是更新后可能会发生不同的事情:
答案 0 :(得分:3)
好的,我设法自己解决了所有问题,因此我决定与您分享解决方案。 :)
使用动态编程和段树,我走在正确的轨道上,但是在以前的尝试中,以错误的方式喂入了段树。
以下是我们在 O(登录)时间内支持更新的方式: 想法是使用一个二进制段树,其中树的叶子代表当前数组,每个节点存储4个不同的值。
对于后代,我指的是同样是叶子的节点的后代。
更新数组时,我们先更新叶子的值,然后再更新其所有祖先的根。由于在每个节点上我们都已经知道了其两个子节点的所有这4个值,因此我们可以轻松计算当前父节点的新4个值。仅举一个例子: v1_current_node = min(v2_leftchild + v1_rightchild,v1_leftchild + v1_rightchild,v1_leftchild + v3_rightchild)。其他所有三个值都可以用类似的方式计算。
由于每个叶子只有 O(logn)个祖先,并且所有4个值都是在 O(1)中计算的,因此只需要 O(登录)。该时间来更新整个树。
现在我们知道每个节点的 4 值,我们可以使用类似的方法,通过从第一个节点到第 n 个节点来计算最低成本:树中路径中 2 的最高幂的节点加起来为 n 。例如,如果 n = 11 ,我们想知道从第一个节点到第十一个节点的最低成本,这可以通过使用覆盖 1-8 叶子的节点的信息来完成>,该节点覆盖树叶 9-10 和树叶节点 11 。对于所有这三个节点,我们都知道所描述的 4 值,并且我们可以通过类似的方式组合该信息来找出答案。最多我们需要考虑使用 O(logn)节点,这样就不会出现问题。