I believe that you can get this to work in amortized O (log n) time to access an element or change a value using a splay tree modification. The idea of the approach is twofold. First, instead of storing the array as an array, we save it as an array pair containing the original values, and a splay tree, where each node key is an index in the array. For example, given an array of seven elements, the setup might look like this:
Array: 3 1 4 2 5 9 3 Tree: 3 / \ 1. 5 / \. / \ 0. 2 4. 6
Note that the tree contains indexes in the array, not the elements of the array themselves. If we want to find the value in a specific index, we simply search the index of the splay tree by index, and then return the array element to the given position, which requires depreciation of O (log n).
The operation you want to support to change all future values I will call the operation "ceiling", as it sets the ceiling for all values after the current one. One way to think about this is that each element in the array has a ceiling associated with it (which is initially infinite), and the true value of the element is the minimum value of its true value and ceiling. The trick is that, using the splay tree, we can adjust the ceiling of all values at a certain point or outside as a result of the depreciation of O (log n). To do this, we expand the splay tree, saving at each node the value of c, which represents the ceiling superimposed on this element forward, and then, if necessary, make the appropriate changes to c.
For example, suppose we want to impose a ceiling from an element forward. Assume that this element is already in the root of the tree. In this case, we simply set the value of c for the new ceiling O (1) times. From this point of view, whenever we look at some value that comes into this element or after it, we can record the ceiling when we go down the tree from the root to the element in question. More generally, when we do a search, every time we follow the correct child link, we mark the value c of this node. As soon as we click on the element in question, we know this ceiling of the element, because we can just take the minimum ceiling of the nodes on the way from the root, whose right children we followed. Thus, to find an element in the structure, we perform a standard search in the splay tree, tracking the value of c, we send, then we print the minimum value of the value of the original value and the value of c.
But in order to make this work, our approach must take into account the fact that the splay tree makes rotations. In other words, we need to show how to propagate the values of c during rotation. Suppose we want to make this turn:
A. B /. ->. \ B. A
In this case, we do not change any values of c, since any value looked after A passed through A node anyway. However, if we do the opposite rotation and extend A above B, then we set the value of A c to at least the value of B c and the value of A c, because if we go down to the left subtree after the rotation, we need B of the ceiling. This means that we perform O (1) per rotation, and since the amortized number of revolutions performed for each playback is O (log n), we amortise O (log n) for each search.
To complete the image, to update an arbitrary ceiling, we will display a node whose ceiling should be changed to the root, and then set its value to c.
In short, we have O (log n) search O (log n) change time (amortized).
This idea is based on a discussion of the link / cut-out trees from the original paper by Slator and Tarjan, “Self-Regulating Binary Search Trees,” which also presents a play tree.
Hope this helps!