【问题标题】:Lazy propagation for Segmented Tree分段树的延迟传播
【发布时间】:2015-08-14 17:28:54
【问题描述】:

对于分段树的惰性传播算法,我有一些不清楚的地方。根据下面的代码,当查询间隔完全重叠时,更新值只是添加到父节点,子节点被标记为延迟更新。但是正如您在所附图片中看到的那样,如果对范围 0,1 进行了 +4 更新,那么两棵树的结果完全不同! (左图:没有延迟传播)。

void update_tree(int node, int a, int b, int i, int j, int value) {
if(lazy[node] != 0) { // This node needs to be updated
    tree[node] += lazy[node]; // Update it

    if(a != b) {
        lazy[node*2] += lazy[node]; // Mark child as lazy
            lazy[node*2+1] += lazy[node]; // Mark child as lazy
    }

    lazy[node] = 0; // Reset it
}

if(a > b || a > j || b < i) // Current segment is not within range [i, j]
    return;

if(a >= i && b <= j) { // Segment is fully within range
        tree[node] += value;

    if(a != b) { // Not leaf node
        lazy[node*2] += value;
        lazy[node*2+1] += value;
    }

        return;
}

update_tree(node*2, a, (a+b)/2, i, j, value); // Updating left child
update_tree(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

tree[node] = max(tree[node*2], tree[node*2+1]); // Updating root with max value}

所以问题是,如果在 +4 更新后调用了一个询问 0,1 总和的查询,该怎么办?

【问题讨论】:

    标签: algorithm data-structures clrs interval-tree


    【解决方案1】:

    首先,您实现的目的似乎是为 2 个操作提供服务。

    1. [i, j] 范围内的所有元素增加值v
    2. 查询[i, j]范围内的max值(我从最后一行看到)

    您询问的是查询范围的总和,这可能无法通过您更新tree[node] 的方式实现。

    其次,您应该使用 update 函数和 query 函数的惰性传播。

    我假设您正在尝试查询 max 范围 [i, j] 的值。你应该可能会得到一些这样的代码:

    int query_max(int node, int a, int b, int i, int j) {
        if(lazy[node] != 0) { // This node needs to be updated
            tree[node] += lazy[node]; // Update it
            if(a != b) {
                lazy[node*2] += lazy[node]; // Mark child as lazy
                lazy[node*2+1] += lazy[node]; // Mark child as lazy
            }
            lazy[node] = 0; // Reset it
        }
        if(a > b || a > j || b < i) // Current segment is not within range [i, j]
            return -INFINITY;
        }
        if(a >= i && b <= j) { // Segment is fully within range
            return tree[node];
        }
        return max(query_max(node*2, a, (a+b)/2, i, j), query_max(node*2+1, a, (a+b)/2+1, i, j));
    }
    

    【讨论】:

    • 我想使用惰性传播,但要使用 sum 而不是 max。那不可能吗?是的,我还为查询实现了惰性传播。
    • 如果用for sum,你只需要稍微调整一下,只要时刻记住你树中每个节点的含义,并相应地更新和查询。
    【解决方案2】:

    好的,我找到了一种正确的方法来更新分段树,该方法使用延迟传播来获取该链接中的总和。

    Lazy propagation for sums

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-25
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-01
      相关资源
      最近更新 更多