Editorial for Yet Another Contest 9 P3 - Divide and Delete
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
Subtask 1
First, let's try to determine whether a given array is good. Consider the -th element,
. This element's index can only ever decrease, so it can never be divided by a number greater than
. Thus, a necessary condition is that for each
,
is a product of positive integers not exceeding
; this is equivalent to saying that the largest prime factor of
is at most
.
On the other hand, this condition is also sufficient. We can show this inductively:
- If the array is empty, we are already done.
- Otherwise, for each
, while
is divisible by
, divide
by
. After this, the largest prime factor of
is now at most
, since it was at most
before division, and
does not divide
.
- Delete the first element, which is allowed since
is guaranteed to be
for arrays satisfying the condition.
- Now, every other element's index decreases by 1, but the condition still holds. So we can inductively show that the remaining array can be made empty.
We can precalculate the largest prime factor of each integer from up to
by modifying the Sieve of Eratosthenes.
For convenience, define as the largest prime factor of
. We now know that the condition for the subarray spanning the indexes
to be valid is that
for all
. For this subtask, it is sufficient to brute force all
, and loop to find the largest
such that the subarray
is valid.
Time complexity:
Subtask 2
We need to speed up the counting of valid subarrays.
For a fixed , define index
as blocking if and only if
. The condition that the subarray spanning the indexes
is valid is now equivalent to saying that there are no blocking indexes between
and
.
Loop from
down to
. The key insight here is that once an indexes stops becoming blocking, it will never become blocking again for any smaller
. Thus, it suffices to maintain a stack of all blocking indexes. That is, when we try a new
, we first add
onto the stack, and then pop off from the stack whilst the top element is non-blocking. The largest value of
such that the subarray
is valid is now the value on the top of the stack, minus
.
Alternatively, for each , we can binary search for the largest
such that subarray
is valid, though we need a quick way to check whether
is valid. This can be done efficiently using a sparse table, or by walking down a segment tree.
Time complexity: or
Comments