Iterative Segment Tree

Here is what the structure looks like for 𝑛=7:

The blue nodes shown are those which are relevant to the query [7,11). Also note that some nodes, in this case 1 and 3, will never be accessed. In particular:

  • If a node has an odd index 𝑖 and its corresponding range can be doubled to the left, its parent 𝑖2 will represent that doubled range.
  • If a node has an even index 𝑖 and its corresponding range can be doubled to the right, its parent 𝑖2 will represent that doubled range.
  • Otherwise, 𝑖2 is useless.

For instance, node 7 corresponds to the range [0,1), which cannot be doubled to the left as it would result in the range [1,1). Therefore, its parent, node 3, is useless.

Similarly, node 6 corresponds to the range [5,7) which also cannot be doubled to the right as it would result in the range [5,9), which is out of bounds of our array.

Walking

Consider the following problem: given a range [𝑙,𝑟) and a predicate 𝑓, find the smallest 𝑚[𝑙,𝑟) such that

𝑓(((𝑖[𝑙,𝑚]𝑎𝑖)))=1

where 𝑓 is either 0 or 1 and also monotonically increasing in 𝑚. If no such 𝑚 exists, return 𝑟.

Consider the following algorithm:

  1. Initialize 𝑣=1. This is the accumulator for our partial product.
  2. Let 𝑢=𝑙+𝑛. While 𝑢 is a left child and its parent’s range does not contain 𝑟, set 𝑢 to its parent.
  3. If 𝑓(𝑣𝑠𝑢)=0, where 𝑠𝑢 denotes the accumulation of 𝑢‘s range [𝑙𝑢,𝑟𝑢), set 𝑙=𝑟𝑢.
  4. Otherwise, set 𝑟=𝑟𝑢1.
  5. If 𝑙=𝑟, return 𝑟. Otherwise, repeat from step 2.

Note that step 2 can be done in 𝒪(1) time by the following snippet:

int u = l + n, x = __lg(min(u & -u, r - l));
u >>= x;

Therefore, the overall runtime of this algorithm is 𝒪(log𝑛).

Here is a clean implementation.

Sparse Segtree

https://codeforces.com/blog/entry/60837