LIS(最长上升子序列)分析:
sequence : -7 10 9 2 3 8 8 1
temp LIS :
position :
sequence :(-7)10 9 2 3 8 8 1
temp LIS : -7
position : 1 // -7 在 LIS 的第一個位置
sequence : -7(10) 9 2 3 8 8 1
temp LIS : -7 10
position : 1 2 // 10 在 LIS 的第二個位置,以此類推。
sequence : -7 10 (9) 2 3 8 8 1
temp LIS : -7 9
position : 1 2 2
/* 9 成為 LIS 的潛力比 10 大, 所以以 9 代替 10 */
sequence : -7 10 9 (2) 3 8 8 1
temp LIS : -7 2
position : 1 2 2 2
/* 2 成為 LIS 的潛力比 9 大, 所以以 2 代替 9 */
sequence : -7 10 9 2 (3) 8 8 1
temp LIS : -7 2 3
position : 1 2 2 2 3
sequence : -7 10 9 2 3 (8) 8 1
temp LIS : -7 2 3 8
position : 1 2 2 2 3 4
sequence : -7 10 9 2 3 8 (8) 1
temp LIS : -7 2 3 8
position : 1 2 2 2 3 4 4
/* 8 成為 LIS 的潛力比 8 大, 所以以 8 代替 8 */
sequence : -7 10 9 2 3 8 8 (1)
temp LIS : -7 1 3 8
position : 1 2 2 2 3 4 4 2
/* 1 成為 LIS 的潛力比 2 大, 所以以 1 代替 2 *
路径输出的话就是倒序输出(dp的长度就是最长子序列的长度),从len到1,t–,找到第一个pos[i]=t的地方输出。
sequence : -7 10 9 2 3 8 (8) 1
position : 1 2 2 2 3 4 (4) 2
LIS : - - - 8
/* search 4th, 8 is fourth LIS element */
sequence : -7 10 9 2 (3) 8 8 1
position : 1 2 2 2 (3) 4 4 2
LIS : - - 3 8
/* search 3rd, 3 is third LIS element */
sequence : -7 10 9 (2) 3 8 8 1
position : 1 2 2 (2) 3 4 4 2
LIS : - 2 3 8
/* search 2nd, 2 is second LIS element */
sequence :(-7)10 9 2 3 8 8 1
position : (1) 2 2 2 3 4 4 2
LIS : -7 2 3 8
/* search 1st, -7 is first LIS element */
下面是代码(利用了STL中自带的二分函数,lower_bound(找到第一个大于a[i]的位置))
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = (int)1000 + 10;
int a[maxn],dp[maxn];
int pos[maxn];//记录位置
int list[maxn];//记录路径
int n;
int main(){
scanf("%d",&n);
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
for(int i = 1;i<=n;i++) scanf("%d",&a[i]);
int len=1;
int po = 1;
dp[1] = a[1],pos[1]= 1;
for(int i = 2;i<=n;i++){
if(a[i]>dp[len]){
dp[++len] = a[i];
pos[++po] = len;//用来记录从a[i]中1到n每个位置的在dp中的位置
} //a[i] -7 10 9 2 3 8 8 1
else{ //pos[j] 1 2 2 2 3 4 4 2
int cnt = lower_bound(dp+1,dp+len+1,a[i]) - dp;
dp[cnt] = a[i];
pos[++po] = cnt;
}
}
//for(int i = 1;i<=n;i++) printf("%d",pos[i]);
int t = len;
for(int i = n;i>=1;i--){
if(pos[i] == t){
list[t--] = a[i];
}
if (t<1) break;
}
for(int i = 1;i<=len;i++) printf("%d\n",list[i]);
return 0;
}