先說最簡單的作法:數組
一種是最多見的dp方法,令f[i]表示以A[i]元素結尾的LIS長度,那麼,F[i]=max{F[j]+1) 其中1<=j<i,A[j]<A[i],邊界是初始化F[i]=1,複雜度O(n^2)。數據結構
#include <cstdio> #include <algorithm> using namespace std; #define FOR(i,a,b) for(int i=(a);i<=(b);++i) int n, a[1005], f[1005]; int main () { scanf("%d", &n); FOR(i, 1, n) scanf("%d", &a[i]), f[i] = 1; FOR(i, 1, n) FOR(j, 1, i - 1) if (a[j] < a[i]) f[i] = max(f[i], f[j] + 1); int ans = 0; FOR(i, 1, n) ans = max(ans, f[i]); printf("%d\n", ans); return 0; }
另外一種是有些貪心思想,利用二分:spa
若是子序列長度相同,那麼最末尾的元素越小,就越有優點,因而對於長度相同的子序列,咱們老是用更小的來替換。code
#include <cstdio> #include <algorithm> using namespace std; const int inf=0x3f3f3f3f; int a[1005], n; int main() { for (int i = 0; i < 1005; ++i) a[i] = inf; scanf("%d", &n); for (int i = 0, t; i < 1005; ++i) { scanf("%d", &t); *lower_bound(a, a + n, t) = t; } printf("%d\n", lower_bound(a, a + n, inf) - a); return 0; }
另外一種,用樹狀數組,這種方法和第一種方法思路是一致的,只不過在尋找比本身小的元素中,最長的那個LIS的過程,利用了樹狀數組來加速。以前的思想是:當前元素的LIS是位置在本身以前的,且LIS是最大的那個值+1。先不論樹狀數組是怎麼工做的,對於原始數組v,複製一個數組a來排序,以後遍歷數組v。這裏因爲是按順序遍歷v的,因此對於v[i],先操做的元素確定位置上在v[i]以前。blog
而後,對於v[i],獲得其在a中的位置p,想辦法獲得在p以前的LIS長度是多少(就是操做query(p-1)),假設是q,那麼ans=max(ans, q+1)。這裏,因爲對於v[i]實際操做的是p,p是v[i]值大小的相對位置,因而又知足:在位置p前面的那些元素,必然大小是<v[i]的,綜上,的確能夠贊成:這和以前LIS解法一的思想是一致的了。排序
如今的要講樹狀數組怎麼工做,即如何完成上面的」想辦法「,無非就是要完成查詢位置p以前的最大值(區間最大值),以及對於當前元素v[i]和其在a中位置的p,獲得LIS後更新位置p以前的LIS。以往BIT老是用來求區間和,其實這只是它的一個應用,說到底它是一個數據結構,方法就是將sum和add的加法操做變成最值操做。 理解到這兒:其實,這徹底能夠用線段數來實現,只不過這裏要處理的區間剛好是[1, p],即剛好必定是從1開始的,用樹狀數據能簡單解決,就沒必要用線段數了。it
#include <cstdio> #include <algorithm> using namespace std; #define FOR(i,a,b) for(int i=(a);i<=(b);++i) #define maxN 10005 int n, L, v[maxN], a[maxN], T[maxN]; void update(int i, int x) { for (; i <= L; i += i & -i) T[i] = max(T[i], x); } int query(int i) { int ans = 0; for (; i; i -= i & -i) ans = max(ans, T[i]); return ans; } int main () { scanf("%d", &n); FOR(i, 0, n - 1) scanf("%d", &v[i]), a[i] = v[i]; sort(a, a + n); L = unique(a, a + n) - a; int ans = 1, t; FOR(i, 0, n - 1) { int p = lower_bound(a, a + L, v[i]) - a + 1; t = query(p - 1) + 1; ans = max(ans, t); update(p, t); } printf("%d\n", ans); return 0; }