D - Divide Interval Editorial by evima
Another SolutionI will describe a policy that recurses top-down. (It is almost the same as the recursive implementation of a segment tree.) Hereafter, let \([l, r)\) denote the sequence \(l, l+1, \dots, r-2, r-1\).
For a good sequence \([l, r)\), let \(f(l, r, L, R)\) denote the optimal partition of the intersection between it and the input sequence \([L, R)\). (We ignore the case without intersection.) The answer is \(f(0, 2^{60}, L, R)\).
Let’s determine \(f(l, r, L, R)\) recursively.
- If the entirety of \([l, r)\) is contained in \([L, R)\), the intersection is \([l, r)\), and this itself is the optimal “partition.”
- Otherwise, let \(m = (l + r) / 2\). Here, both the left half \([l, m)\) and the right half \([m, r)\) of \([l, r)\) are good sequences.
- If the entirety of \([L, R)\) is contained in the left half \([l, m)\), that is, if \(R \leq m\), the right half can be ignored, and the optimal partition is \(f(l, m, L, R)\).
- If the entirety of \([L, R)\) is contained in the right half \([m, r)\), that is, if \(m \leq L\), the left half can be ignored, and the optimal partition is \(f(m, r, L, R)\).
- If neither of the above conditions is met, then \([L, R)\) intersects with both the left and right halves of \([l, r)\), and the optimal partition is the concatenation of \(f(l, m, L, R)\) and \(f(m, r, L, R)\).
Implementing this as a recursive function and calling \(f(0, 2^{60}, L, R)\) will result in the number of recursive calls being four or less per layer (see the diagram in the official editorial), with a total of \(60 \times 4\) calls or less.
Sample Implementation (Python):
def f(l, r, L, R):
if L <= l and r <= R:
return [(l, r)]
m = (l + r) // 2
if R <= m:
return f(l, m, L, R)
if m <= L:
return f(m, r, L, R)
return f(l, m, L, R) + f(m, r, L, R)
L, R = map(int, input().split())
ans = f(0, 1 << 60, L, R)
print(len(ans))
for l, r in ans:
print(l, r)
posted:
last update: