2Brute2Best
🔥0
01

Classic LIS (DP — Longest Increasing Subsequence Sub-pattern)

The plain LIS and its cousins: length, count of longest chains, maximum-sum chain, or just "is there a chain of 3".

Signals in the problem statement
  • ›

    "longest increasing subsequence"

  • ›

    "number of longest increasing subsequences"

  • ›

    "maximum sum increasing subsequence"

  • ›

    "increasing triplet"

What makes it different

The cell value changes (length, count, sum) but the rule "extend the best earlier j with a smaller value" doesn't. Only the plain length has the O(N log N) tails trick.

Questions

ordered from “learn the idea” to “recognise it without help”
  1. 1
    Longest Increasing Subsequence
    Basic Anchor·LeetCode #300
    Medium
  2. 2
    Increasing Triplet Subsequence
    Basic Reinforcement·LeetCode #334
    Medium
  3. 3
    Max Sum Increasing Subsequence
    Slight Variation·GeeksforGeeks
    Medium
  4. 4Medium

Template

lis-template.cpp
// O(N^2): dp[i] = length of the longest increasing chain that ends at i.
int lisQuadratic(const vector<int>& a) {
    int n = a.size(), best = 0;
    vector<int> dp(n, 1);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < i; j++)
            if (a[j] < a[i]) dp[i] = max(dp[i], dp[j] + 1);
        best = max(best, dp[i]);
    }
    return best;
}

// O(N log N): tails[k] = smallest last value of an increasing chain of length k + 1.
// tails is sorted; it gives the LENGTH only, not the chain itself.
int lisFast(const vector<int>& a) {
    vector<int> tails;
    for (int x : a) {
        auto it = lower_bound(tails.begin(), tails.end(), x);   // upper_bound for non-decreasing
        if (it == tails.end()) tails.push_back(x);   // longer than every chain so far
        else *it = x;                                // a smaller tail for that length
    }
    return tails.size();
}
Remember this · DP — Longest Increasing Subsequence
Trigger
Longest chain where each item must be bigger/fit inside the previous one (numbers, pairs, envelopes, words).
Think
Does each element extend the best chain ending at some smaller earlier element?
Key question
Sort first? Then what does "increasing" mean for these items?