Set A[t] denotes the number of T in the sequence, f[t] represents the length of the longest ascending subsequence ending in T from 1 to T, with the initial setting F [t] = 0 (t = 1, 2, ..., Len (A)). Then there is the dynamic programming equation: f[t] = max{1, f[j] + 1} (j = 1, 2, ..., t-1, and A[j] < a[t]).
Now, let's consider the case of calculating f[t] carefully. Suppose there are two elements a[x] and a[y] that meet
(1) x < y < T
(2) A[X] < A[y] < A[t]
(3) F[X] = F[y]
At this point, choose F[x] and select F[y] All can get the same f[t] value, then, in this position of the longest ascending subsequence, should choose A[x] or should choose A[y]?
Obviously, choosing a[x] is better than choosing a[y]. Because of the condition (2), in a[x+1] ... A[T-1] In this section, if there is a[z],a[x] < A[z] < A[y], then a longer ascending sequence will be obtained compared to selecting A[y].
Again, depending on the condition (3), we will get a revelation: classify according to the value of f[]. For each value K of f[], we only need to preserve the minimum value in all A[t] that meet f[t] = k. Set D[k] To record this value, i.e. d[k] = min{a[t]} (f[t] = k).
Note the two features of d[]:
(1) The value of d[k] is monotonous and does not degrade during the whole calculation.
(2) The value of d[] is ordered, i.e. d[1] < d[2] < D[3] < ... < d[n].
Using d[], we can get another method to calculate the length of the longest ascending subsequence. The longest ascending sequence length that is currently calculated is Len. First Judge A[t] and D[len]. If a [t] > D[len], then a[t] will get a longer ascending subsequence after D[len], len = len + 1, D[len] = a [t]; otherwise, in d[1]. D[len], find the largest J, meet D[j] < a[t]. K = j + 1, there is a [t] <= D[k], will a[t] after D[j] will get a longer ascending subsequence, update d[k] = a[t]. Finally, Len is the length of the longest ascending subsequence required.
In the above algorithm, if you use the naïve order to find in d[1]. D[len] Find, because a total of O (n) elements need to calculate, the complexity of each calculation is O (n), the entire algorithm time complexity of O (n^2), compared with the original algorithm has no progress. However, due to the characteristics of d[] (2), when we find in d[], we can use the binary search to complete efficiently, the time complexity of the entire algorithm is reduced to O (Nlogn), with a very significant increase. It is important to note that d[] does not record the longest ascending subsequence that conforms to test instructions after the algorithm is finished!
1#include <cstdio>2#include <cstring>3#include <algorithm>4#include <iostream>5 using namespacestd;6 7 Const intmx=100005;8 intA[MX],D[MX];9 Ten intBinserch (intLintRintcut) One { A while(l<=R) - { - intM= (l+r) >>1; the if(cut>d[m]&&cut<=d[m+1])returnm; - if(Cut>d[m]) l=m+1; - Elser=m-1; - } + return 0; - } + A intLIS (intN) at { - intlen=1, J; -d[1]=a[0]; - for(intI=1; i<n;i++) - { - if(A[i]>d[len]) j=++Len; in ElseJ=binserch (1, Len,a[i]); -d[j]=A[i]; to } + returnLen; - } the * intMain () $ {Panax Notoginseng intN; - while(~SCANF ("%d",&N)) the { + for(intI=0; i<n;i++) scanf ("%d",&a[i]); Aprintf"%d\n", LIS (n)); the } +}
Longest ascending subsequence (Lis algorithm (Nlong (n)))