• 51nod 1134 最长递增子序列 (O(nlogn)算法)


    基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
     收藏
     关注
    给出长度为N的数组,找出这个数组的最长递增子序列。(递增子序列是指,子序列的元素是递增的)
    例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10。
     
    Input
    第1行:1个数N,N为序列的长度(2 <= N <= 50000)
    第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9)
    Output
    输出最长递增子序列的长度。
    Input示例
    8
    5
    1
    6
    8
    2
    4
    5
    10
    Output示例
    5

    常规的解法是设dp[i]表示前i位的最长上升序列长度,然后每次更新dp[i+1]都要与[0,i]进行一次比较。
    时间复杂度为O(n^2),完美超时。

    想想怎么去优化呢?看看更新dp[i+1]需要比较这么多次吗?假设dp[i+1]=len,那么我们只要与值为len-1的去
    进行比较,所以不妨设b[i]表示最长上升序列为i的dp数组中的最小值。

     1 /*用数组b来存放最长上升序列,然后枚举数组a中元素看能否插入b数组。
     2 那么b数组的大小即为所求。
     3 */
     4 #include <iostream>
     5 #include <algorithm>
     6 #include <cstring>
     7 using namespace std;
     8 typedef long long ll;
     9 ll b[50005];
    10 ll a[50005];
    11 ll n;
    12 void solve()
    13 {
    14     memset(b,0,sizeof(b));
    15     b[0]=a[0];
    16     int sum=1;
    17     for(int i=1;i<n;i++)//枚举a数组
    18     {
    19         int pos=lower_bound(b,b+sum,a[i])-b;//lower_bound()返回值为b数组中有几个比a[i]小的
    20         b[pos]=a[i];                                //或者理解为用a[i]去更新b序列应更新的位置
    21         sum=max(sum,pos+1);//长度更新
    22     }
    23     cout<<sum<<endl;
    24 }
    25 int main()
    26 {
    27     cin>>n;
    28     for(int i=0;i<n;i++)
    29         cin>>a[i];
    30     solve();
    31     return 0;
    32 }
    代码才是最清晰的语言
  • 相关阅读:
    TCP详解——传输控制协议(总述)
    sublime text3使用插件SublimeTextTrans设置透明度
    vue学习1
    js事件绑定/监听
    如何成为顶级程序猿
    HTML5中meta属性
    windows安装SVN服务器并设置开机启动
    oracle安装登录sqlplus / as sysdba然后报错ERROR: ORA-01031 insufficient privileges
    移动端和PC端有什么区别
    div+css通用兼容性代码整理
  • 原文地址:https://www.cnblogs.com/onlyli/p/7242906.html
Copyright © 2020-2023  润新知