int n;
vector<int> A, p;// predecessor array
void print_LIS(int i) { // backtracking routine
if (p[i] == -1) {
cout << A[i] << " ";
return;
}// base case
print_LIS(p[i]); // backtrack
cout << A[i] << " ";
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
// note: A[n] must be set as the largest value ("INF")
// so that all LIS (that can start anywhere) will end at n
cin >> n;
A.assign(n + 1, 0);
for (int i = 0; i < n; ++i) {
cin >> A[i];
}
A[n] = INF; // set A[n] = INF
cout << "n = " << n << ": ";
for (int i = 0; i < n; ++i)
cout << A[i] << " ";
cout << "\n";
int k = 0, lis_end = 0;
vi L(n, 0), L_id(n, 0);
p.assign(n + 1, -1);
for (int i = 0; i < n; ++i) { // O(n)
int pos = lower_bound(L.begin(), L.begin() + k, A[i]) - L.begin();
L[pos] = A[i]; // greedily overwrite this
L_id[pos] = i; // remember the index too
p[i] = pos ? L_id[pos - 1] : -1; // predecessor info
if (pos == k) { // can extend LIS?
k = pos + 1; // k = longer LIS by +1
lis_end = i; // keep best ending i
}
}
cout << "Final LIS is of length " << k << ": ";
print_LIS(lis_end);
return 0;
}