最长上升子序列

摘自《挑战程序设计竞赛》如有错误,请指正!

(1)

  定义:dp[ i ]表示以Ai为末尾的最长上升子序列。

  以Ai结尾的上升子序列是:①只包含Ai的子序列②再满足 j < i 并且Aj < Ai 的以Aj为结尾的子序列,追加上Ai后得到的子序列。

  于是,dp[ i ]=max(1,dp[ j ]+1 | j<i and aj<ai)。

  复杂度O(n²)

 1 int n;
 2 int a[maxn],dp[maxn];
 3 
 4 void sovle(){
 5     int res=0;
 6     for(int i=0;i<n;i++){
 7         dp[i]=1;
 8         for(int j=0;j<i;j++) if(a[j]<a[i]) dp[i]=max(dp[i],dp[j]+1);
 9         res=max(res,dp[i]);
10     }
11     cout<<res<<endl;
12 }
13  

(2)

  前面我们用DP求取针对最末尾的元素的最长的子序列。如果子序列的长度相同,那么最末尾的元素较小的在之后会更加有优势,所以我们反过来用DP针对

       相同长度情况下最小的末尾元素进行求解。

  定义:dp[ i ]表示长度为i+1的上升子序列中末尾元素的最小值(不存在的话就INF)。

  复杂度O(nlogn)

1 int n;
2 int a[maxn],dp[maxn];
3 
4 void sovle(){
5     fill(dp,dp+n,INF);
6     for(int i=0;i<n;i++) *lower_bound(dp,dp+n,a[i])=a[i];
7     int ans=lower_bound(dp,dp+n,INF)-dp;
8     cout<<ans<<endl;
9 }

 

posted @ 2017-08-03 22:41  天之道,利而不害  阅读(90)  评论(0编辑  收藏  举报