1. O(n²) DP
dp[i] = 1
for i in 0..n-1:
for j in 0..i-1:
if a[j] < a[i]:
dp[i] = max(dp[i], dp[j] + 1)
dp[i] = LIS ending at i
Binary search piles
Track parents
dp[i] = 1
for i in 0..n-1:
for j in 0..i-1:
if a[j] < a[i]:
dp[i] = max(dp[i], dp[j] + 1)
piles = []
for x in a:
place x on leftmost pile with top >= x (binary search)
length = len(piles)
Piles store minimal tail for subsequences of each length; they are non-decreasing.
Maintain predecessor indices and an array of pile ends (indices), then backtrack from last pile.