• POJ 2533 Longest Ordered Subsequence


            题目大意:求一个数列的最长上升子序列(严格上升)。

            解题思路:

    方法一:O(n^2)

    dp[i]:表示处理到第i个位置,序列的最长上升子序列末尾为i的长度; a[]数组存储原序列

    dp[i] = max{dp[j]+1},a[i]>a[j],0≤j≤i

    方法二:O(nlogn)

         复杂度降低其实是因为这个算法里面用到了二分搜索。本来有N个数要处理是O(n),每次计算要查找N次还是O(n),一共就是O(n^2);现在搜索换成了O(logn)的二分搜索,总的复杂度就变为O(nlogn)了。

         这个算法的具体操作如下:

         开一个栈,每次取栈顶元素top和读到的元素temp做比较,如果temp > top 则将temp入栈;如果temp < top则二分查找栈中的比temp大的第1个数,并用temp替换它。最长序列长度即为栈的大小top。

        道理:对于数列中的a[i] 和a[j] ,i < j , 假设a[ i ]已在栈stap中,a[ j ] 未在栈中,这时读到元素a[ j ] , 如果a[ j ] < a[ i ](此时a[j]必然小于栈顶元素), 将a[j]与 a[i] 互换,此时这个栈的大小没有变化,但这个栈的“潜力”变大了,因为如果存在a[ j ] < a[ z ] < a[ i ] (i < j < z) ,当a[ i ]为栈顶元素时,a[ j ] 替换 a[ i ]后成为栈顶元素,此后在读到a[ z  ] 时就能把a[z] 压入栈,栈的大小就增加 1 , 即最长上升子序列长度就增加了1。

        举例:原序列为1,5,8,3,6,7

        栈为1,5,8,此时读到3,用3替换5,得到1,3,8; 再读6,用6替换8,得到1,3,6;再读7,得到最终栈为1,3,6,7。最长递增子序列为长度4。

    请看代码:

     

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<string>
    #include<algorithm>
    #include<cmath>
    using namespace std ;
    const int MAXN = 1e3 + 5 ;
    int s[MAXN] ;
    int dp[MAXN] ;
    int n ;
    int stap[MAXN] ;
    int top ;
    void init()
    {
        int i , j ;
        for(i = 1 ; i <= n ; i ++)
        {
            scanf("%d" , &s[i]) ;
        }
    }
    void solve()  // O(n^2) 算法
    {
        int i , j ;
        dp[1] = 1 ;
        for(i = 2 ; i <= n ; i ++)
        {
            dp[i] = 1 ;
            for(j = 1 ; j < i ; j ++)
            {
                if(s[i] > s[j] && dp[i] < dp[j] + 1)
                {
                    dp[i] = dp[j] + 1 ;
                }
            }
        }
        int MAX = -1 ;
        for(i = 1 ; i <= n ; i ++)
        {
            if(MAX < dp[i])
            MAX = dp[i] ;
        }
        printf("%d
    " , MAX) ;
    }
    
    void solve2()  // O(n log n) 算法
    {
        top = 0 ;
        stap[++ top] = s[1] ;
        int i ;
        for(i = 2 ; i <= n ; i ++)
        {
            if(s[i] > stap[top])
            {
                stap[++ top] = s[i] ;
            }
            else if(s[i] < stap[top])
            {
                int left , right , mid ;
                left = 1 ;
                right = top ;
                while (left < right)
                {
                    mid = (left + right) / 2 ;
                    if(stap[mid] < s[i])
                    {
                        left = mid + 1 ;
                    }
                    else if(stap[mid] == s[i])
                    {
                        break ;
                    }
                    else
                    {
                        right = mid ;  // 注意不是 mid - 1  !!
                    }
                }
                mid = (left + right) / 2 ;
                stap[mid] = s[i] ;
            }
        }
        printf("%d
    " , top) ;
    }
    int main()
    {
        while (scanf("%d" , &n) != EOF)
        {
            init() ;
            //solve() ;
            solve2() ;
        }
        return 0 ;
    }
    

     

     


  • 相关阅读:
    xt
    UVA 10200 Prime Time (打表)
    CodeForces 540B School Marks
    CodeForces 540C Ice Cave (BFS)
    poj 3250 Bad Hair Day(栈的运用)
    hdu A Magic Lamp
    hdu 4325 Flowers(区间离散化)
    hdu 5500 Reorder the Books
    V2X之标准
    V2X的前生今世
  • 原文地址:https://www.cnblogs.com/james1207/p/3283389.html
Copyright © 2020-2023  润新知