最长上升子序列

https://www.cnblogs.com/frankchenfu/p/7107019.html 借鉴

最长上升子序列就是在一个序列中找到非递减的子序列,子序列可以不是连续的

一种方法就是固定一个i在0到i中找j j取或不取将影响到i 更新i的值 复杂度是O(n^2)

#include<cstdio>
const int MAX=1001;
int a[MAX];
int lis(int x)
{
    int num[MAX];
    for(int i=0;i<x;i++)
    {
        num[i]=1;
        for(int j=0;j<i;j++)
        {
            if(a[j]<a[i]&&num[j]+1>num[i])
                   num[i]=num[j]+1;
        }
    }
    int maxx=0;
    for(int i=0;i<x;i++)
        if(maxx<num[i])
            maxx=num[i];
    return maxx;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    return !printf("%d\n",lis(n));
}

今天考到的第二个方法是用栈优化的 复杂度是O(nlgn)

用二分的思想....【其实我也不是特别理解】 这个二分其实是用stl lower_bound实现的

dp[i]=长度为i+1的上升子序列中末尾元素的最小值(不存在的话就是INF)

http://blog.csdn.net/zhangyx_xyz/article/details/50949957【参考】


几乎都没有用过的我感到非常惭愧 还去百度了一下是什么

函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置


#include<cstdio>
#include<algorithm>
const int MAXN=200001;

int a[MAXN];
int d[MAXN];

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    d[1]=a[1];
    int len=1;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>d[len])
            d[++len]=a[i];
        else
        {
            int j=std::lower_bound(d+1,d+len+1,a[i])-d;
            d[j]=a[i]; 
        }
    }
    printf("%d\n",len);    
    return 0;
}


posted @ 2018-01-30 20:52  wyboooo  阅读(122)  评论(0编辑  收藏  举报