To solve LIS in O(n log n) we use the patience-sorting / "tails" approach: tails[len] stores the smallest possible tail value of an increasing subsequence of length len+1 seen so far. For each number x, binary-search the leftmost tails[i] >= x and replace it; if x is larger than all tails, append it. The length of tails is the LIS length.Code (with reconstruction using parent and indices):cpp
#include <bits/stdc++.h>
using namespace std;
vector<int> reconstructLIS(const vector<int>& nums) {
int n = nums.size();
vector<int> tails; // stores values for binary search
vector<int> tails_idx; // stores indices in nums corresponding to tails
vector<int> parent(n, -1); // parent pointers to reconstruct
for (int i = 0; i < n; ++i) {
int x = nums[i];
auto it = lower_bound(tails.begin(), tails.end(), x);
int pos = it - tails.begin();
if (it == tails.end()) {
tails.push_back(x);
tails_idx.push_back(i);
} else {
*it = x;
tails_idx[pos] = i;
}
if (pos > 0) parent[i] = tails_idx[pos-1];
}
// Reconstruct: start from index tails_idx.back()
vector<int> lis;
if (!tails_idx.empty()) {
int cur = tails_idx.back();
while (cur != -1) {
lis.push_back(nums[cur]);
cur = parent[cur];
}
reverse(lis.begin(), lis.end());
}
return lis;
}
int lengthOfLIS(const vector<int>& nums) {
vector<int> tails;
for (int x : nums) {
auto it = lower_bound(tails.begin(), tails.end(), x);
if (it == tails.end()) tails.push_back(x);
else *it = x;
}
return tails.size();
}
int main() {
vector<int> nums = {10,9,2,5,3,7,101,18};
cout << "LIS length: " << lengthOfLIS(nums) << "\n";
auto lis = reconstructLIS(nums);
cout << "LIS: ";
for (int v : lis) cout << v << " ";
cout << "\n";
}
Key points:- tails[i] = smallest tail of an increasing subsequence with length i+1; this greedy choice keeps future extension options maximal.- Use lower_bound to maintain strictly increasing subsequence (replace >= ensures strictly increasing).- Time: O(n log n) due to binary searches; Space: O(n).- Reconstruction requires storing indices and parent pointers; when you update tails_idx[pos] with current index i, set parent[i] = tails_idx[pos-1] (if pos>0). Edge cases: empty input, duplicates handled by lower_bound behavior. Example input yields length 4 and one LIS [2,3,7,18].