给定一个序列,求出它的最长上升子序列或者是最长不下降子序列的长度 或者输出这个子序列

一、动态规划 O(n^2)

1.求长度

首先来讨论最长上升子序列的情况,即子序列是严格上升的

假如我们以dp[i]表示以a[i]为结尾的上升子序列的长度 那么对于 j (1<=j<i),如果a[j]<a[i],很显然:

dp[i] = max(dp[i], dp[j]+1);
当然先要赋初值,dp[i]=1,因为一开始只有它自己组成这个序列
最后每次计算出dp[i]之后都要对答案进行更新
至于最长不下降子序列,只需要把a[j]<a[i]改为a[j]<=a[i]即可

代码:

#include <bits/stdc++.h>  

using namespace std; 

int anss=,i,n,j,a[],dp[];

int main()
{
cin>>n;
for(i=;i<n;i++)
{
cin>>a[i];
}
for(i=;i<n;i++)
{
dp[i]=;
for(j=;j<i;j++)
{
if(a[j]<a[i]) //如果是最长不下降子序列就改为 if(a[j]<=a[i])
{
dp[i]=max(dp[j]+,dp[i]);
}
}
if(dp[i]>anss)
anss=dp[i];
}
cout<<anss<<endl;
}

2.求序列

只需要从dp数组向前遍历,找到dp[i]==anss的之后再找dp[i]==anss-1的....以此类推即可

#include <bits/stdc++.h>  

using namespace std; 

int anss=,i,n,j,a[],dp[];

int main()
{
cin>>n;
for(i=;i<n;i++)
{
cin>>a[i];
}
for(i=;i<n;i++)
{
dp[i]=;
for(j=;j<i;j++)
{
if(a[j]<a[i])
{
dp[i]=max(dp[j]+,dp[i]);
}
}
if(dp[i]>anss)
anss=dp[i];
}
cout<<anss<<endl;
}

不过通常最长上升子序列的解是不唯一的,长度是唯一的。

二、贪心 O(nlogn)

对于一个上升子序列,显然其结尾元素越小,越有利于在后面接其他的元素,也就越可能变得更长。

因此,我们只需要维护 dp 数组(虽然已经不是动态规划了),对于每一个a [ i ],如果a [ i ]能接到 LIS 后面,就接上去;否则,就用 a [ i ] 取更新 dp数组:在dp数组中找到第一个大于等于a [ i ]的元素dp[ j ],用a [ i ]去更新dp [ j ]。怎么找到第一个大于等于的元素呢?只需要使用lower_bound()函数即可。
至于最长不下降子序列,只需要将 “在dp数组中找到第一个大于等于a [ i ]的元素dp[ j ]” 这一步改为找到第一个大于的元素即可。同样的将lower_bound换成upper_bound()

1.代码

#include <bits/stdc++.h>  

using namespace std; 

int anss=,i,n,j,a[],dp[],temp;

int main()
{
cin>>n;
for(i=;i<n;i++)
{
cin>>a[i];
dp[i]=0x7ffffff;
}
for(i=;i<n;i++)
{
temp=lower_bound(dp,dp+n,a[i])-dp;
if(temp+>anss)
{
anss++;
}
dp[temp]=a[i];
}
cout<<anss<<endl;
}

2.求序列

只需要另外开一个数组b,记录dp[i]的位置,然后从b数组向前遍历,找到b[i]==anss的之后再找b[i]==anss-1的....以此类推

#include <bits/stdc++.h>  

using namespace std; 

int anss=,i,n,j,a[],dp[],temp,b[],c[];

int main()
{
cin>>n;
for(i=;i<n;i++)
{
cin>>a[i];
dp[i]=0x7ffffff;
}
for(i=;i<n;i++)
{
temp=lower_bound(dp,dp+n,a[i])-dp;
if(temp+>anss)
{
anss++;
}
dp[temp]=a[i];
b[i]=temp;
}
cout<<anss<<endl;
temp=anss-;
for(i=n-;i>=;i--)
{
if(b[i]==temp)
{
c[temp]=a[i];
temp--;
}
}
for(i=;i<anss;i++)
{
cout<<c[i]<<' ';
}
}

最长上升(不下降)子序列(LIS) 不同求解方法(动规、贪心)的更多相关文章

  1. 最长非降/下降子序列问题(DP)(待续...)

    注意:抽象成以下描述即为最长非降/下降子序列问题(一维状态) 问题描述:在一个无序的序列a1,a2,a3,a4…an里,找到一个最长的序列满足:(不要求连续) ai<=aj<=ak…< ...

  2. Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列)

    Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列) Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺 ...

  3. SPOJ 3943 - Nested Dolls 最长不下降子序列LIS(二分写法)

    现在n(<=20000)个俄罗斯套娃,每个都有宽度wi和高度hi(均小于10000),要求w1<w2并且h1<h2的时候才可以合并,问最少能剩几个. [LIS]乍一看跟[这题]类似, ...

  4. HDU 1087 最长不下降子序列 LIS DP

    Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. May ...

  5. hdu 4604 Deque(最长上升与下降子序列-能够重复)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4604 这个题解有点问题,暂时没时间改,还是参考别人的吧 #include <cstdio> ...

  6. 求最长非降(递增)子序列LIS的长度,及注意事项

    非降序列(Increasing Sequence)例如: (1) 完全递增型序列:S={1,3,6,7,9} (2) 部分存在等于的序列:S={1,3,3,6,9} S的非降子序列:由原序列S的元素组 ...

  7. Longest Ordered Subsequence POJ - 2533 dp 最长上升/不下降 子序列

    #include<iostream> using namespace std ; ; int f[N]; int a[N]; int n; int main() { cin>> ...

  8. 动态规划——最长不下降子序列(LIS)

    最长不降子序列是这样一个问题: 下面介绍动态规划的做法. 令 dp[i] 表示以 A[i] 结尾的最长不下降序列长度.这样对 A[i] 来说就会有两种可能: 如果存在 A[i] 之前的元素 A[j] ...

  9. HDU 6357.Hills And Valleys-字符串非严格递增子序列(LIS最长非下降子序列)+动态规划(区间翻转l,r找最长非递减子序列),好题哇 (2018 Multi-University Training Contest 5 1008)

    6357. Hills And Valleys 自己感觉这是个好题,应该是经典题目,所以半路选手补了这道字符串的动态规划题目. 题意就是给你一个串,翻转任意区间一次,求最长的非下降子序列. 一看题面写 ...

随机推荐

  1. Mysql: 开启慢查询日志[ERROR] unknown variable 'log-slow-queries'处理办法

    参考: http://www.dataguru.cn/thread-305503-1-1.html # slow query log qjp 20160921 # mysql5.6版本以上,取消了参数 ...

  2. C/C++ - 指针 与 引用

    一.指针 1.指针与指针变量的区分 a.指针:指针就是内存编号,也就是内存地址,通俗的讲,指针就是变量的地址. 注1:指针的大小是根据计算机的操作系统而定的,跟变量类型无关 注2:如果是32位的操作系 ...

  3. Nowcoder 练习赛26 D xor序列 ( 线性基 )

    题目链接 题意 : 中文题.点链接 分析 : 对于给定的 X 和 Y 假设存在一个 Z 使得 X (xor) Z = Y 做一个变形 X (xor) Z (xor) Y = 0 X (xor) Y = ...

  4. [洛谷P1501] [国家集训队]Tree II(LCT模板)

    传送门 这是一道LCT的板子题,说白了就是在LCT上支持线段树2的操作. 所以我只是来存一个板子,并不会讲什么(再说我也不会,只能误人子弟2333). 不过代码里的注释可以参考一下. Code #in ...

  5. 02.替换空格 (Java)

    题目描述 请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 思路 感觉这题对于Java意义 ...

  6. JAVA_OPT理解及调优理论

    以RocketMQ的namesrv和broker启动为例,理解CMS和G1垃圾收集器下的jdk参数 CMS垃圾收集器 以RocketMQ中runserver.cmd为例,这是启动NameSrv的命令行 ...

  7. springboot 集成 druid mybatis-plus

    通过这篇配置成功: https://www.cnblogs.com/shine-rainbow/p/9618100.html 不过 mybatis 3.4.6 一直maven下载失败,于是直接在官方那 ...

  8. 后盾网lavarel视频项目---lavarel用户认证实例

    后盾网lavarel视频项目---lavarel用户认证实例 一.总结 一句话总结: 主要是用的Auth认证,所以配置是配置的auth(config/auth.php),控制器中调用也是用的Auth( ...

  9. Git:本地项目与远程仓库的git/clone

      版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_40197828/article/details/79283278 初识Git命令行将本地项 ...

  10. 怎样用 Bash 编程:逻辑操作符和 shell 扩展

    学习逻辑操作符和 shell 扩展,本文是三篇 Bash 编程系列的第二篇. Bash 是一种强大的编程语言,完美契合命令行和 shell 脚本.本系列(三篇文章,基于我的 三集 Linux 自学课程 ...