Prefix MEX#12785

Prefix MEX (Editorial)

Problem author:

Maryan Shyika

Prepared by:

Maryan Shyika

Tutorial:

Maryan Shyika

Idea

Let

b=[a_L,a_{L+1},\ldots,a_R].

For convenience, convert the query range [l,r] into coordinates of the original array:

X=L+l-1,\qquad Y=L+r-1.

We consider the cases k=1, k=2, and k\ge 3 separately.

k=1

For the current value of , maintain the array

c_i=f([a_L,a_{L+1},\ldots,a_i]).

For L=1, this array can be built with a standard left-to-right scan while maintaining the current MEX.

Now consider the transition from to L+1. Let

v=a_L.

Let be the next position after where the value occurs. If there is no such position, set p=n+1.

After removing a_L, prefix MEX values may change only before the next occurrence of , that is, up to position p-1.

Let be the first position such that

c_x>v.

Then after moving to L+1, the new prefix MEX on the whole segment

[x,p-1]

becomes equal to . Therefore, we need to perform

c_i=v

for all i\in[x,p-1].

To maintain the array , we use a segment tree supporting:

  • range assignment;

  • range sum;

  • finding the first position such that c_x>v.

Then the answer to a query with k=1 is

\sum_{i=X}^{Y}c_i.

k=2

Let

d=f(c).

Since the array is nondecreasing, the value of increases by one whenever the next required value

0,1,2,\ldots

appears in for the first time.

Let p_x be the first position where the value occurs in .

The value affects the answer only if the first occurrences form the chain

p_0<p_1<\ldots<p_x.

In this case, the appearance of increases the prefix MEX at every position starting from p_x. Therefore, it corresponds to the operation

d_i\gets d_i+1

for all

i\in[p_x,n].

Thus, the array can be maintained using a second segment tree that supports range addition and range sum queries.

When moving from to L+1, the structure of first occurrences changes, and therefore the initial strictly increasing chain

p_0<p_1<p_2<\ldots

may also change.

If some values become part of this chain, we apply

[p_x,n]\gets +1.

If some values stop being part of the chain, we apply

[p_x,n]\gets -1.

These changes can be maintained amortized, so the total number of updates over the whole sweep over is linear.

Then the answer to a query with k=2 is

\sum_{i=X}^{Y}d_i.

k\ge 3

After the third application of , the array is guaranteed to become constant.

If a_L=0, then the first element of is equal to , so contains no zero. Therefore,

f^2(b)=[0,0,\ldots,0],

and

f^3(b)=[1,1,\ldots,1].

If a_L\ne0, then the first element of is equal to . After one more application of , every element of the resulting array is positive, so

f^3(b)=[0,0,\ldots,0].

After that, every further application of simply alternates between a constant array of zeros and a constant array of ones.

Therefore, for k\ge3,

g(k,b)=[1,1,\ldots,1]

if and only if

(a_L=0)\mathbin{\mathrm{XOR}}(k\bmod 2=0).

Otherwise,

g(k,b)=[0,0,\ldots,0].

Hence, the answer to a query with k\ge3 is either

r-l+1,

or .

Complexity

We process values of sequentially from to .

For k=1, each transition takes O(\log n).

For k=2, each segment tree update takes O(\log n), while the total number of required changes is linear amortized.

Each query with k=1 or k=2 is answered in O(\log n), while a query with k\ge3 is answered in .

Therefore, the overall time complexity is O((n+q)\log n).

The memory complexity is O(n+q).