Longest Array Deconstruction (Codeforces 1575L)
Tags: DP, divide and conquer

Mr. Chanek gives you a sequence $$$a$$$ indexed from $$$1$$$ to $$$n$$$. Define $$$f(a)$$$ as the number of indices where $$$a_i = i$$$. You can pick an element from the current sequence and remove it, then concatenate the remaining elements together. For example, if you remove the $$$3$$$-rd element from the sequence $$$[4, 2, 3, 1]$$$, the resulting sequence will be $$$[4, 2, 1]$$$. You want to remove some elements from $$$a$$$ in order to maximize $$$f(a)$$$, using zero or more operations. Find the largest possible $$$f(a)$$$.

Input: The first line contains one integer $$$n$$$ ($$$1 \leq n \leq 2 \cdot 10^5$$$) — the initial length of the sequence.The second line contains $$$n$$$ integers $$$a_1, a_2, \ldots, a_n$$$ ($$$1 \leq a_i \leq 2 \cdot 10^5$$$) — the initial sequence $$$a$$$.

Output: Output an integer denoting the largest $$$f(a)$$$ that can be obtained by doing zero or more operations.

Note: In the first example, $$$f(A) = 3$$$ by doing the following operations.$$$[2,1,\textbf{4},2,5,3,7] \rightarrow [\textbf{2},1,2,5,3,7] \rightarrow [1,2,5,3,\textbf{7}] \rightarrow [1,2,\textbf{5},3] \rightarrow [1,2,3]$$$In the second example, $$$f(A) = 2$$$ and no additional operation is needed.

Sample Inputs:
7
2 1 4 2 5 3 7

4
4 2 3 1

Sample Outputs:
3

2

Solution (Python):
import bisect
n = int(input())
a = list(map(int, input().split()))
temp = []
for i in range(n):
    temp.append((a[i], i + 1 - a[i]))
temp.sort(key=lambda x: (x[0], -x[1]))
seq = []
for t in temp:
    (a, d) = t
    if d >= 0:
        pos = bisect.bisect_right(seq, d)
        if pos == len(seq):
            seq.append(d)
        else:
            seq[pos] = d
print(len(seq))

Solution (Python):
import bisect
n = int(input())
a = list(map(int, input().split()))
couple = []
for i in range(n):
    couple.append((a[i], i + 1 - a[i]))
couple.sort(key=lambda x: (x[0], -x[1]))
seq = []
for j in couple:
    (a, d) = j
    if d >= 0:
        pos = bisect.bisect_right(seq, d)
        if pos == len(seq):
            seq.append(d)
        else:
            seq[pos] = d
print(len(seq))

Solution (Python):
import bisect
n = int(input())
a = list(map(int, input().split()))
couple = []
for i in range(n):
    couple.append((a[i], i + 1 - a[i]))
couple.sort(key=lambda x: (x[0], -x[1]))
seq = []
for j in couple:
    (a, d) = j
    if d >= 0:
        pos = bisect.bisect_right(seq, d)
        if pos == len(seq):
            seq.append(d)
        else:
            seq[pos] = d
print(len(seq))