zoukankan      html  css  js  c++  java
  • DP经典--百练2757--最长上升子序列

    题意描述

    有三种解法 n^2 和两个n*log(n)         一个讲得很好的博客:地址

    n^2的,动态规划:

    动归问题,首先很容易认为这道题的子问题就是,求前n个数字序列的解,这样的错误之处在于,“状态具有后效性”,前n个数字序列的解可能有多种,每一种可能结尾数字不一样,这样对后面的解就有了影响(后效性)

    比较好的子问题是,求以第n个数为结尾的数字序列的解,这样的子问题,便没有了后效性

    事实上,我认为第一种子问题如果加以处理也能消除后效性,但是我思考了一下觉得这样子会很麻烦,有兴趣的同学可以试试,一起讨论一下~

    确定了子问题剩下的就很简单

    ac代码:

    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    using namespace std;
    
    #define maxn 1000+10
    #define inf 1<<31
    
    int dp[maxn],num[maxn];
    
    int main(){
        int n,ans=-1;
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>num[i];dp[i]=1;
            for(int j=1;j<i;j++){
                if(num[j]<num[i]){
                dp[i]=max(dp[i],dp[j]+1);
                }
            }
        }
        cout<<*max_element(dp+1,dp+n+1);
        return 0;
    } 

    n*log(n)的,贪心+二分:

    新建一个low数组,low[i]表示长度为i的LIS结尾元素的最小值。对于一个上升子序列,显然其结尾元素越小,越有利于在后面接其他的元素,也就越可能变得更长。因此,我们只需要维护low数组,对于每一个a[i],如果a[i] > low[当前最长的LIS长度],就把a[i]接到当前最长的LIS后面,即low[++当前最长的LIS长度]=a[i]。 
    那么,怎么维护low数组呢? 
    对于每一个a[i],如果a[i]能接到LIS后面,就接上去;否则,就用a[i]取更新low数组。具体方法是,在low数组中找到第一个大于等于a[i]的元素low[j],用a[i]去更新low[j]。如果从头到尾扫一遍low数组的话,时间复杂度仍是O(n^2)。我们注意到low数组内部一定是单调不降的,所有我们可以二分low数组,找出第一个大于等于a[i]的元素。二分一次low数组的时间复杂度的O(lgn),所以总的时间复杂度是O(nlogn)。

    ac代码:

    #include<cstdio>
    #include<algorithm>
    
    #define maxn 1000+10
    
    int lower[maxn],num[maxn]; 
    
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&num[i]);
        }
        int ans=1;
        lower[1]=num[1];
        for(int j=2;j<=n;j++){
         if(num[j]>lower[ans]){
             lower[++ans]=num[j];
         }
         else{
             int l=std::lower_bound(lower+1,lower+ans,num[j])-lower;
             lower[l]=num[j];
         }
        }
        printf("%d
    ",ans);
        return 0;
    }

    最后这种方法看起来比较麻烦,用到了树状数组,我还没有学到,篮桥北貌似也不考这个,因此以后在更吧~

    柳暗花明又一村
  • 相关阅读:
    Mac电脑maven安装与配置
    解决Mac OS X中IDEA启动慢以及debug卡死问题
    如何在Mac上启用root用户或更改root密码
    mac文本编辑器软件,五大适用于Mac修订的文本编辑器,nodepad++替代软件
    mac系统到10.14以上,navicat无法打开,一直显示已损坏解决办法
    mac苹果电脑AppleID注册或者登录appstore时提示:您没有完整填写表格,请输入您的出生年份的解决方法
    mac苹果电脑使用相关,开发环境配置指南(持续更新)
    bitmap to base64
    Multiple actions were found that match the request in Web Api
    vue get attribute value
  • 原文地址:https://www.cnblogs.com/ucandoit/p/8496086.html
Copyright © 2011-2022 走看看