最长上升子序列
 这类动规问题可以从规模比现在小的情况下开始,而在规模较小的情况下还有规模更小的情况,一直到只有一个点。也就是以每个点为终点的最长上升子序列的长度都是1。然后对于某一个点,遍历从下标为1到这个点的前一个点的数,如果比它下,那么以这个点为终点的最长上升子序列的长度就可以加1了。
 最终代码思路为:初始化每个dp数组下标的值都为1,然后对于每个点来说,都可以用它前面的几个点来更新,如果这个值比他前面的某个值要大,那么以这个点为终点的长度加1。
 这个问题向外延伸出最长不下降子序列,最长下降子序列等等。
名词解释:
 一串数字比如1、5、3、6、9、8、10,它的子序列是从左到右不连续的若干个数,比如1、5、6,3、9、8、10都是它的子序列。
 最长上升子序列即从左到右严格增长的最长的一个子序列,1、5、6、9、10就是这个序列的一个最长上升子序列。
 给出若干序列,求出每个序列的最长上升子序列长度。
Input
 多组数据,每组第一行正整数n,1 <= n <= 1000,第二行n个空格隔开的不大于1,000,000的正整数。
Output
 每组数据输出一行,最长上升子序列的长度。
Sample Input
 7
 1 5 3 6 9 8 10
Sample Output
 5
using namespace std;
int a[1005], dp[1005];
int n;
int main()
{
  while (scanf("%d", &n)!=EOF){
    for (int i=1; i<=n; i++){
      scanf("%d", &a[i]);
      dp[i]=1;
    }
    for (int i=1; i<=n; i++){
      for (int j=1; j<i; j++){
        if (a[i]>a[j])
          dp[i]=max(dp[i], dp[j]+1);
      }
    }
    int maxx=0;
    for (int i=1; i<=n; i++)
      maxx=max(maxx, dp[i]);
    printf("%d\n", maxx);
  }
  return 0;
}lower_bound优化, nlogn复杂度
 dp[i]表示长度为i的子序列最大的那个数是dp[i]
using namespace std;
int a[1005];
int dp[1005];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    dp[1]=a[1];
    int len=1;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>dp[len])
            dp[++len]=a[i];
        else
        {
            int j=upper_bound(dp+1,dp+len+1,a[i])-dp;
            dp[j]=a[i]; 
        }
    }
    printf("%d\n",len);    
    return 0;
}                
                










