更新数组

时间:2016-01-05 19:16:18

标签: algorithm segment-tree

给定一个初始化为0的数组arr,即arr [i] = 0,其中0 <0。我&lt; n

在它上面执行两个操作

  1. 更新k r x

    更新执行以下操作:

    for(i=k;i<=r;i++)
    {
        arr[i]=x;
        x+=x;
    }
    
  2. 查询k r

    查询计算以下总和:

    for(i=k;i<=r;i++)
    {
        sum+=arr[i];
    }
    print(sum);
    
  3. 我的解决方案:
    我想到了蛮力,但它很慢。我想到了段树,但是在段树更新中是以恒定量执行的,所以它失败了。什么可能是一个很好的算法来解决这个问题?

    约束

    数组的大小是&lt; = 10 ^ 5

    操作次数(更新,查询)&lt; = 10 ^ 5

1 个答案:

答案 0 :(得分:2)

您正在寻找的是细分树中的延迟传播。 我们创建一个数组lazy [],其大小与段树数组的大小相同。我们的想法是,我们可以通过推迟更新来避免更新中的递归调用,并仅在需要时执行这些更新。

我的代码执行预定义数据的更新和总和提取,您可以使用main来接受所需模式中的用户数据,并添加x + = x等调整。

https://ideone.com/kZsJ0E

我建议您打开代码并并排阅读下面的解释,以便更好地理解,因为懒惰传播通常很难掌握。

工作原理:

  • 最初,lazy []数组中的所有条目都设置为0,这意味着在该节点所代表的范围内没有剩余的工作要做。
  • 更新数组索引的分段树,从qs(查询开始)到qe(查询结束):

    - &GT;如果当前段树节点有任何挂起 更新,然后我们分配该节点(lazy_value)*(它表示的间隔长度)并将其子项的延迟值指定为new_value

    - &GT;如果当前节点的范围完全在 更新查询范围。

    i) Update the Current node, by assigning it (lazy_value)*(length of interval it represents)
    
    ii) Postpone updates to children by setting lazy values for children nodes as new_value
    

    - &GT;如果当前节点的范围与更新重叠 范围,遵循与上述相同的方法 更新

    一个。重复左右儿童。

    湾使用left的结果更新当前节点   和正确的电话。

  • 现在,当我们使用get_sum过程时,如果当前节点有任何挂起的更新并且推迟了对子节点的更新,我们也会更新当前节点。

总的来说,这里很难解释懒惰传播的整个工作,但我希望代码和解释有所帮助。

有关延迟传播的更多信息,请参阅

https://www.hackerearth.com/notes/segment-tree-and-lazy-propagation/