修改分段树中的延迟传播

时间:2014-01-24 19:59:45

标签: c++ algorithm segment-tree

我最近阅读了段树中的懒惰传播并对其进行了编码。但是当我假设而不是添加值(= val)时我被卡住了,我需要除以值。如何做? 请帮忙

我的更新功能如下:

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
}

1 个答案:

答案 0 :(得分:0)

HINTS

假设您需要除以固定的K值。

一种可能性是将您的数字转换为基数K,并且在每个节点中保持数字A []的数组,其中A [i]是位置i中所有数字的所有较低节点中的总数(当被认为是基数K数。)

因此,例如,如果K为10,则A [0]将存储所有单位的总数,而A [1]将存储所有单位的总数。

这样做的原因是它很容易被懒惰地划分为K,所有你需要做的就是设置A [i] = A [i + 1]并且你可以使用与你的相同的懒惰更新技巧代码。

实施例

假设我们有一个阵列5,11,20,100而K是10

我们将为元素5,11构造一个包含值:

的节点
Total = A[1]*10+A[0]*1 with A[1]=1 and A[0]=5+1 (the sum of the unit values)

我们还有一个20,100的节点,其中包含值:

Total = A[2]*100+A[1]*10+A[0]*1 with A[2]=1,A[1]=2,A[0]=0

和整个5,11,20,100数组的节点:

Total = A[2]*100+A[1]*10+A[0]*1 with A[2]=1,A[1]=2+1,A[0]=5+1

如果我们想将整个数组除以10,我们只需更改顶部节点的数组元素:

A=[1,3,6] changes to [0,1,3]

然后我们可以通过计算来查询所有节点的总和:

Total = A[2]*100+A[1]*10+A[0]*1 = 0*100+1*10+3*1=13

相同
(5/10=0)+(11/10=1)+(20/10=2)+(100/10=10)