0

对于分段树的惰性传播算法,我有一些不清楚的地方。根据下面的代码,当查询间隔完全重叠时,更新值只是添加到父节点,子节点被标记为延迟更新。但正如您在所附图片中看到的那样,如果对范围 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 和的查询怎么办?

4

2 回答 2

1

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

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

您正在询问查询范围的总和,这对于您更新tree[node].

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

我假设您正在尝试查询maxrange 的值[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));
}
于 2015-08-14T17:46:46.667 回答
0

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

总和的延迟传播

于 2015-08-14T17:51:40.397 回答