zoukankan      html  css  js  c++  java
  • zoj1986,poj1631,最长上升子序列,复杂度O(n*logn)

    链接:http://poj.org/problem?id=1631

    题意:最长上升子序列。复杂度为O(n*logn).

    思路:这道题只能用nlogn的算法,n^2的话会卡掉。

    下面这两个个链接介绍nlogn的算法讲的还可以。

    http://www.cnblogs.com/celia01/archive/2012/07/27/2611043.html

    http://blog.sina.com.cn/s/blog_4b1e4fe9010098af.html

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn=40005;
    int n,a[maxn],d[maxn];
    
    int binarysearch(int l,int r,int p)
    {
        int mid=(l+r)/2;
        while(l<=r)
        {
            if(d[mid]<p && p<=d[mid+1])
               return mid;
            if(d[mid]<p) l=mid+1;
            else r=mid-1;
            mid=(l+r)/2;
        }
    }
    int solve()
    {
        int len=1;
        d[1]=a[1];
        for(int i=2;i<=n;i++)
        {
            if(a[i]>d[len])
            {
                len++;
                d[len]=a[i];
            }
            else
            {
                int k=binarysearch(1,len,a[i]);
                d[k+1]=a[i];
            }
        }
        return len;
    }
    int main()
    {
    //    freopen("ine.cpp","r",stdin);
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            printf("%d
    ",solve());
        }
        return 0;
    }
    View Code

    上面这个写法比较好懂,《训练指南》上讲了另一种写法,短了很多。

    如下:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn=40005;
    const int INF=1000000;
    int n,a[maxn],d[maxn];
    
    int main()
    {
    //    freopen("ine.cpp","r",stdin);
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            fill(d,d+n,INF);
            for(int i=1;i<=n;i++)
                *lower_bound(d,d+n,a[i])=a[i];
            printf("%d
    ",lower_bound(d,d+n,INF)-d);
        }
        return 0;
    }
    View Code

    上面使用的STL中的fill()函数和lower_bound()函数。

    简略简绍下。

    fill()函数它的原理是把那一块单元赋成指定的值,与memset不同,
    memset则是按字节填充的。

    例如:

    int main()
    {
        int  d[100];
        fill(d,d+100,1);
        for(int i=0; i<100; i++)
            cout<<d[i]<<" ";
        cout<<endl;
        memset(d,1,100*sizeof(int));
        for(int i=0; i<100; i++)
            cout<<d[i]<<" ";
        cout<<endl;
    }

    使用fill()函数,数组d[]中的元素都赋值为数字1,使用memset()函数,数组d[]中的元素都赋值为数字(1<<24)+(1<<16)+(1<<8)+1  =  16843009.

    iterator lower_bound( const key_type &key ): 返回一个迭代器,指向键值>= key的第一个元素。

    iterator upper_bound( const key_type &key ):返回一个迭代器,指向键值> key的第一个元素。

    lower_bound()在 [first , last) 这个前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置。(注意:此时数组下标越界)

    upper_bound()也是在 [first , last) 这个前闭后开区间进行二分查找,如果插入元素大于数组中全部元素,返回的是last。注意:此时数组下标越界)

  • 相关阅读:
    eclipse设置字体大小
    如何利用服务器下发的Cookie实现基于此Cookie的会话保持
    Docker学习笔记_安装和使用Python
    Docker学习笔记_安装和使用mysql
    Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.38/images/json: dial unix /var/run/docker.sock: conne
    Ubuntu18.04创建新的系统用户
    Docker学习笔记_安装和使用nginx
    Docker安装和使用Tomcat
    虚拟机ubuntu18.04设置静态IP
    我学习参考的网址
  • 原文地址:https://www.cnblogs.com/54zyq/p/3268025.html
Copyright © 2011-2022 走看看