The basic idea of finding the longest descent subsequence is the same as that of LIS, which is a classic DP topic.
Most of the problems are similar to the fact that there is a sequence A1, A2, a3... AK... An, which requires the length of the longest descent sub-sequence (or the longest descent sub-sequence.
Take the longest descent subsequence as an Example
Use a [I] to store the I-th element (I: 1 to n) of sequence)
When F [I] is used to represent the element at the first I position, the longest son sequence is f [I].
O (N ^ 2) solution:
That is to say, between 1 --- I-1, we must find the element a [J] whose subscript is J so that f [J] is the largest of F [1] --- F [I-1, then f [I] = f [J] + 1.
(Note that a [J]> A [I] must be satisfied.)
When I (1 to n) is used to obtain f [1] -- F [N], the largest of F [1] -- F [N] Is ans.
State transition equation:
F [I] = 1 (I = 1) // only the first character
F [I] = f [J] + 1 (a [I] <A [J]) // if the maximum value is not decreased, a [I]> = A [J] is satisfied.
Code implementation:
// H [I] is the parent sequence, DP [I] indicates the longest descent sub-sequence length obtained after calculating H [] I at the position I. ans indicates the longest descent sub-sequence length. // F [I] indicates the maximum length of the sub-sequence obtained after I position is H [] I? Is the longest length of the sub-sequence without dropping # include <cstdio> # include <cstring> # include <cmath> # include <algorithm> using namespace STD; # define maxint 0x7f7f7f7fconst int n = 100000; int H [N], DP [N], F [N]; int main () {// freopen ("in.txt", "r", stdin ); // freopen (". TXT "," W ", stdout); int n = 1; int ans =-maxint, min =-maxint; while (scanf (" % d ", & H [N])! = EOF) {n ++;} DP [1] = f [1] = 1; for (INT I = 1; I <n; I ++) {DP [I] = 1; F [I] = 1; for (Int J = 1; j <I; j ++) {If (DP [J] + 1> DP [I] & H [J]> H [I]) DP [I] = DP [J] + 1; if (F [J] + 1> F [I] & H [J] <H [I]) f [I] = f [J] + 1 ;}} for (INT I = 1; I <n; I ++) {If (ANS <DP [I]) {ans = DP [I];} if (Min <F [I]) min = f [I];} printf ("% d \ n", ANS, min); Return 0 ;}View code
O (N * logn) Solution
Ideas:
Make the array C [k] record the minimum value of a [I] When F [] = K, Len indicates that the length of the Child column is decreased at this time.
There are two conditions at the position I
1. A [I] <C [K]. If the descending order is met, you only need to connect a [I] to C [K], Len + 1;
2. A [I]> = C [K], you need to find a minimum value a [J] greater than a [1] to C [K], then place a [I] at J + 1, Len = k = J + 1.
Because C [k] is not monotonic, the process of searching for a [J] can be divided into two parts. That is why the algorithm complexity reaches O (N * logn.
The final Len value is the length of the eldest son sequence.
Code implementation:
# Include <cstdio> # include <cmath> # include <cstring> # include <algorithm> using namespace STD; const int n = 1000000; // returns the subscript int bsearch (int c [], int Len, int N) {int left = 1, Right = Len, mid; while (left <= right) {mid = (left + right)/2; If (n> C [Mid]) Right = mid-1; else if (n <C [Mid]) Left = Mid + 1; else return mid;} return left;} int A [n], C [N]; int main () {int n = 1, J, Len; int COUNT = 0; // freo Pen ("in.txt", "r", stdin); // freopen ("out.txt", "W", stdout); While (scanf ("% d ", & A [n])! = EOF) {n ++;} C [1] = A [1]; Len = 1; for (INT I = 1; I <n; I ++) {J = bsearch (C, Len, a [I]); C [J] = A [I]; If (j> Len) // not found, description: A [I] <C [K]. Based on the characteristics of binary search, J is better than Len. Add a [I] to the position of C [Len + 1]. Len = J; // update Len} printf ("Ans = % d \ n", Len); Return 0 ;}