我正在解决的问题的一部分涉及在数组范围内获得最小值(RMQ),所以我实现了一个分段树,它到目前为止工作正常。然后我想更新原始数组中的一个项目(没有多个更新)并在段树中更新它。到目前为止我所做的是从上到下遍历段树,直到我到达树叶,但似乎有一些错误。这是代码的更新部分,那里似乎有什么问题?
附: n不是两个的倍数(我不知道这是否会影响解决方案)
public void update(int i, int k) {
update(i, k, 0, 0, n - 1);
}
/// <summary>
/// update one item in the segment tree
/// </summary>
/// <param name="i">The index of the element to be updated in the original array</param>
/// <param name="k">The new value</param>
/// <param name="j">The current index in the segment tree</param>
/// <param name="from">range start index (inclusive)</param>
/// <param name="to">range end index (inclusive)</param>
private void update(int i, int k, int j, int from, int to) {
tree[j] = Math.Min(tree[j], k);
if (from == to) return;
int mid = from + (to - from) / 2;
if (from <= i && mid >= i) {
update(i, k, 2 * j + 1, from, mid);
} else {
update(i, k, 2 * j + 2, mid + 1, to);
}
}
附:问题的其他部分可能存在一些错误,但似乎这是最容易出错的部分。
答案 0 :(得分:1)
您的更新功能无法正确设置和构建段树中的更新值。
private void update(int i, int k, int j, int from, int to) {
if (from == to) {
tree[j] = k; //set the new leaf value.
return;
}
int mid = (from+to)/2;
if (from <= i && mid >= i) {
update(i, k, 2 * j + 1, from, mid);
} else {
update(i, k, 2 * j + 2, mid + 1, to);
}
tree[j] = Math.Min(tree[2*j+1], tree[2*j+2]); //keep correcting minimums for every parents with the current minimum.
}
此外,您在构建和更新树时浪费了大量树空间。为避免额外的空间使用,请使用2*j
和2*j+1
作为当前节点j的子节点。实施应该是这样的:
update(i, k, 2*j, from, mid);
update(i, k, 2*j+1, mid+1, to);