PROBLEM LINK:
Practice
Contest: Division 1
Contest: Division 2
Contest: Division 3
Contest: Division 4
Author: raysh07
Tester: sushil2006
Editorialist: iceknight1093
DIFFICULTY:
TBD
PREREQUISITES:
Dynamic programming
PROBLEM:
A pair of arrays A and B of the same length are said to be perfect if it’s possible to create an array C such that:
- For each i, either C_i = A_i or C_i = B_i.
- C_i \lt C_{i+1} for each 1 \leq i \lt |C|
You’re given two arrays A and B of length N.
Count the number of pairs (L, R) such that 1 \leq L \leq R \leq N and the arrays A[L\ldots R] and B[L\ldots R] are perfect.
EXPLANATION:
First, let’s understand how to decide when a pair of arrays A and B can be perfect, by constructing a valid C.
It’s not hard to see that a simple greedy algorithm works - that is, for each i, choose C_i = \min(A_i, B_i) if this satisfies C_i \gt C_{i-1}, and choose C_i = \max(A_i, B_i) otherwise.
If even the latter fails for some i, (A, B) is not perfect; otherwise it can be.
The proof of this is simple via an exchange argument, applied from left to right.
We now extend this idea to counting the number of valid pairs.
The key observation here is that in our above greedy algorithm, we only really cared about the last element of the array, i.e. when trying to decide the value of C_i, only C_{i-1} matters.
This allows for the use of dynamic programming.
First, for convenience, let’s assume A_i \lt B_i for all i (if not, swap them).
Now define dp(i, 0) to be the number of left endpoints such that the pair (A[L\ldots i], B[L\ldots i]) is perfect, with the last element of the greedily constructed array being A_i.
Similarly, define dp(i, 1) to be the number of valid left endpoint such that the last element of the constructed array is B_i.
To compute dp(i, 0) and dp(i, 1):
- We always have one valid left endpoint for ending with A_i: L = i.
- As for L \lt i, there are a couple of possibilities.
- If A_i \gt B_{i-1}, then it’s always possible to extend a valid subarray ending at i-1, to a valid subarray ending at i by appending A_i.
So, dp(i, 0) = dp(i-1, 0) + dp(i-1, 1) + 1 here.
dp(i, 1) will just be 0. - If B_{i-1} \gt A_i \gt A_{i-1}, only those subarrays ending with A_{i-1} can be extended.
So, dp(i, 0) = dp(i-1, 0) + 1.
dp(i, 1) will be either 0 or dp(i-1, 1), depending on how B_i compares to B_{i-1}. - If A_i \lt A_{i-1}, no extension from smaller indices is possible; so dp(i, 0) = 1.
dp(i, 1) will be the sum of dp(i-1, 0) and/or dp(i-1, 1), depending on how B_i compares to A_{i-1} and B_{i-1}.
- If A_i \gt B_{i-1}, then it’s always possible to extend a valid subarray ending at i-1, to a valid subarray ending at i by appending A_i.
Once all the dp values are known, the final answer is simply the sum of
dp(i, 0) + dp(i, 1)
across all 1 \leq i \leq N.
TIME COMPLEXITY:
\mathcal{O}(N) per testcase.
CODE:
Editorialist's code (PyPy3)
for _ in range(int(input())):
n = int(input())
a = list(map(int, input().split()))
b = list(map(int, input().split()))
for i in range(n):
if a[i] > b[i]: a[i], b[i] = b[i], a[i]
dp = [[1, 0] for i in range(n)]
ans = 1
for i in range(1, n):
if a[i] > b[i-1]: dp[i][0] += dp[i-1][0] + dp[i-1][1]
elif a[i] > a[i-1]:
dp[i][0] += dp[i-1][0]
if b[i] > b[i-1]: dp[i][1] += dp[i-1][1]
else:
if b[i] > a[i-1]: dp[i][1] += dp[i-1][0]
if b[i] > b[i-1]: dp[i][1] += dp[i-1][1]
ans += dp[i][0] + dp[i][1]
print(ans)