0

A part of a problem I'm solving involves getting the minimum in a range of an array (RMQ), so I implemented a segment tree and it works fine so far. Then I want to update one item in the original array (There are no updates with more than one) and update it in the segment tree. What I do so far is traverse the segment tree from top to bottom till I reach the leaves, but there seems to be some bug in this. Here is the update part of the code, what seems to be wrong there ?

P.S. n is not a multiple of two ( I don't know if this affects the solution )

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);
    }
}


P.S. There are other parts of the problem that may have some bugs, but it seems that this is the part most likely to have the bug.

Ayman El Temsahi
  • 2,600
  • 2
  • 17
  • 27
  • The following looks suspicious : tree[j] = Math.Min(tree[j], k); The old value of tree[j] is being lost. Don't you want to swap tree[j] and k? – jdweng Sep 27 '16 at 23:50
  • what do you mean swap tree[j] and k? the tree array is the segment tree array, i want tree[j] to have the min of the subtree below it after modifying the value in the main array – Ayman El Temsahi Sep 27 '16 at 23:58
  • 1
    I haven't verified the algorithm. The code you are using will only work if tree[j] is empty. If tree[j] already contains a value then you are overriding the existing value without saving the results. – jdweng Sep 28 '16 at 09:47

1 Answers1

1

Your update function doesn't set and build up the updated values in the segment tree correctly.

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.
}

Also you are wasting a lot of tree space while building and updating the tree. To avoid extra space usage, use 2*j and 2*j+1 as the child of current node j. Implementation should be something like this:

update(i, k, 2*j, from, mid);
update(i, k, 2*j+1, mid+1, to);
Obaida.Opu
  • 444
  • 1
  • 4
  • 18
  • [Obaida.Opu](https://stackoverflow.com/users/3226143/obaida-opu) Hi. I have used your approach in rmq but I am getting Wrong ans. Please help. [This](https://stackoverflow.com/questions/46129639/range-minimum-query-using-segment-trees-wrong-answer) is the link of my question on stackoverflow. I would be very grateful. Thanks – Brij Raj Kishore Sep 09 '17 at 17:08