Yes, you can adapt Fenwick trees (binary indexed trees) to
- Update value at given index in O (log n)
- Minimum query value for a range in O (log n) (amortized)
We need 2 Fenwick trees and an additional array containing real values ββfor the nodes.
Suppose we have the following array:
index 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 value 1 0 2 1 1 3 0 4 2 5 2 2 3 1 0
The wave of the magic wand and the following trees appear:

Note that in both trees, each node represents the minimum value for all nodes inside this subtree. For example, in BIT2, node 12 has a value of 0, which is the minimum value for nodes 12,13,14,15.
Inquiries
We can efficiently query the minimum value for any range by calculating a minimum of several subtree values ββand another real node value. For example, the minimum value for the range [2,7] can be determined by accepting the minimum value BIT2_Node2 (representing nodes 2,3) and BIT1_Node7 (representing nodes 7), BIT1_Node6 (representing nodes 5,6) and REAL_4 - therefore it covers all nodes in [ 2.7]. But how do we know which trees we want to look under?
Query(int a, int b) { int val = infinity
It can be mathematically proved that both workarounds will end in the same node. This node is part of our range, but it is not part of any subtrees we were looking at. Imagine a case where the (unique) smallest value of our range is in this special node. If we were not looking, our algorithm would give incorrect results. This is why we should do this in a real array of values.
To understand the algorithm, I suggest you simulate it with a pen and paper, looking at the data in the examples above. For example, a range query [4.14] will return a minimum of BIT2_4 (number 4,5,6,7), BIT1_14 (representative 13,14), BIT1_12 (rep. 9,10,11, 12) and REAL_8, therefore, cover all possible values ββ[4, 14].
Update
Since a node is the minimum value of itself and its children, changing the node will affect its parents, but not its children. Therefore, to update the tree, we start with node, we modify and move the entire path to the fictitious root of the node (0 or N + 1, depending on which tree).
Suppose we update some node in some tree:
Pseudocode for updating node with value v in the tree:
while (node <= n+1) { if (v > tree[node]) { if (oldValue == tree[node]) { v = min(v, real[node]) for-each child { v = min(v, tree[child]) } } else break } if (v == tree[node]) break tree[node] = v node = parentOf(node, tree) }
Note that oldValue is the original value that we replaced, while v can be reassigned several times as we move through the tree.
Binary indexing
In my experiments, the Minimum range queries were about twice as fast as the Segment Tree implementation, and the updates were slightly faster. The main reason for this is the use of super-efficient bitwise operations to move between nodes. They are very well described here . Segment trees are really easy to code, so think about how beneficial this performance advantage is. The update method of my Fenwick RMQ is 40 lines and it took some time to debug. If someone wants my code, I can put it on github. I also created tape and test generators to make sure everything works.
I helped to understand this topic and implement it from the community of Finnish algorithms. The source of the image is http://ioinformatics.org/oi/pdf/v9_2015_39_44.pdf , but they attribute the 1994 Fenwick document to it.