CSU 1047 最长上升子序列 (二分水过)

1047: 最长上升子序列

Time Limit: 1 Sec       Memory Limit: 128 Mb       Submitted: 321       Solved: 121    

Description

  名词解释:

一串数字比如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
解题思路:对于求最长上升子序列有很多方法,但是这种方法是非常快的,利用二分来求最长上升子序列

用一个数组a来存上升子序列,当输入的数比数组a的最后一个值还要大的时候,那么直接把这个数增加到数组后面;否则利用二分寻找比它小的最接近的数替换,最后a数组的长度就是最长上升子序列的长度;值得注意的是,这样子不能将序列正确输出,因为中间会出现替换。。。。

代码如下:

二分代码:

#include 
#include 
#include 
#include 
using namespace std;
int a[1005];
int f(int x,int y,int n)///二分查找,返回与之最接近的值的下标
{
    int l=x,r=y;
    while(l>1;
        if(n>a[mid]) l=mid+1;
        else r=mid;
    }
    return l;
}
int main()
{
    int n,b;
    while(~scanf("%d",&n))
    {
        a[0]=-1;
        int t=0;
        for(int i=0;ia[t]) a[++t]=b;
            else if(b

非二分代码:可以同时求出最长上升和下降子序列,但是没有二分快

#include
#include
#include
#include
using namespace std;
const int maxn=10005;
int a[maxn],b[maxn],c[maxn];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int s1=-1,s2=-1;
        for(int i=0; i=a[i]) b[i]=max(b[i],b[j]);///最长下降子序列
                else c[i]=max(c[i],c[j]);///最长上升子序列
            ///s1=max(s1,++b[i]);///最长下降子序列的个数
            s2=max(s2,++c[i]);///最长上升子序列的个数
        }
        printf("%d\n",s2);
    }
    return 0;
}






你可能感兴趣的:(OJ)