• 最长递增子序列LIS再谈


    DP模型:

    d(i) 以第 i 个元素结尾的最长递增子序列的长度。

    那么就有 d(i) = max(d(j)) + 1;(j<i&&a[j]<a[i]),答案 max(d(i)); 时间复杂度为 O(n*n);

    下面介绍一个用二分优化的O(nlogn)的算法。

    用一个数组g[i] 表示 d 值为 i 的数的最小的 a;即 最长递增子序列为 i 时,最小的 a 是多少。

    显然 g[i]<=g[2]<=g[3];

    计算d[i] : 需要找到 g中大于等于a[i] 的第一个数 j ,d[i] = j;

    更新g :     g[j] = a[i] ;

    使用STL的lower_bound可以直接求出比a[i] 大的第一个数,用的二分查找实现,总时间O(nlogn);

    #include <bits/stdc++.h>
    using namespace std;
    
    int a[1005];
    int b[1005];
    
    int main()
    {
    
        int n;
        scanf("%d",&n);
    
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
    
        int len = 1;
        b[0] = a[0];
    
        for(int i=1;i<n;i++) {
            if(a[i]==b[len-1])
                continue;
            if(a[i]>b[len-1])
                b[len++] = a[i];
            else {
                int pos = lower_bound(b,b+len,a[i])-b;
                b[pos] = a[i];
            }
        }
    
        printf("%d
    ",len);
        return 0;
    }
    View Code
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    #define maxn 1005
    #define INF 0x3f3f3f3f
    
    int a[1005];
    int g[1005];
    
    int binary_search(int *s,int digit,int length) {
        int left = 0,right = length,mid;
        while(right!=left) {
            mid = (left+right)/2;
            if(digit==s[mid])
                return mid;
            else if(digit<s[mid])
                right = mid;
            else left = mid+1;
        }
        return left;
    }
    
    int main()
    {
        int n;
        scanf("%d",&n);
    
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
        }
    
        memset(g,INF,sizeof(INF));
    
        g[0] = -1;
        int len = 1;
        int j;
        for(int i=1;i<=n;i++) {
            j = binary_search(g,a[i],len);
    
            if(j==len)
                len++;
            g[j] = a[i];
        }
    
    
        printf("%d
    ",len-1);
        return 0;
    }
    View Code



  • 相关阅读:
    HDU1266 Reverse Number
    codevs1380 没有上司的舞会
    codevs1163 访问艺术馆
    codevs2144 砝码称重 2
    codevs1553 互斥的数
    codevs1230 元素查找
    codevs3118 高精度练习之除法
    codevs1245 最小的N个和
    codevs1063 合并果子
    codevs1052 地鼠游戏
  • 原文地址:https://www.cnblogs.com/TreeDream/p/5988041.html
Copyright © 2020-2023  润新知