博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
最长不下降子序列
阅读量:7122 次
发布时间:2019-06-28

本文共 1067 字,大约阅读时间需要 3 分钟。

最近想复习dp,于是先来水一篇博客。。。

如何来求一个一串长度为\(n\)的数列的最长不下降子序列呢?

\(dp[i]\)表示所有长度为\(i\)的不下降子序列的最小结尾数字。

也就是说\(dp[i]=\{min(j)|len[j]=i\}\)\(len[j]\)表示以\(j\)结尾的不下降子序列长度(实际代码并不要用上这个数组)。

然后就可以愉快的开始dp啦!

初始化\(dp[1]=a[1],ans=1\),从2开始dp

对于每一个\(a[i]\),若\(a[i]\ge dp[ans]\),那么它就可以更新当前答案,所以就令\(dp[++ans]=a[i]\)

若小于呢?则我们需要用上dp数组的单调性了。

我们先来看看dp数组的定义:\(dp[i]=\{min(j)|len[j]=i\}\)

再结合更新过程,我们显然可以得出\(dp[i]\ge dp[i-1]\)的性质

所以如果小于,我们就在\(dp[1\,\,to\,\,ans]\)中找到第一个大于\(a[i]\)的数,把它替换成\(a[i]\)

此时,因为它是第一个大于\(a[i]\)的,所以它之前的数肯定都小于\(a[i]\),所以\(a[i]\)完全可以代替它,且因为\(a[i]\)比它要小,所以带来的价值会更高(贪心)。

具体实现我们可以用STL中的upper_bound(毕竟学的都是C with STL 滑稽.jpg)。时间复杂度\(O(n\,\,log\,\,n)\)

Code:

#include
using namespace std;int n,ans;int a[100001],dp[100001];int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); dp[1]=a[1];ans=1; for(int i=2;i<=n;i++){ if(a[i]>=dp[ans]) dp[++ans]=a[i]; else { int x=upper_bound(a+1,a+ans+1,a[i])-a; dp[x]=a[i]; } } printf("%d\n",ans); return 0;}

转载于:https://www.cnblogs.com/NLDQY/p/10339592.html

你可能感兴趣的文章
老国企如何焕发新势能?致远互联“协同五环”锻造老而弥坚
查看>>
被戴尔收购的EMC宣布明年裁员:人数未定
查看>>
物联网时代MCU 将迎来三大发展趋势
查看>>
解决最后一米信号问题飞鱼星VF-E300全新上市
查看>>
智慧城市安全问题初探
查看>>
打造NFV环境下的专属性能
查看>>
测试用例编写规范
查看>>
SWIFT系统第三家银行曝遭网络劫匪抢走1200万美元
查看>>
Java的GC机制
查看>>
espresso系列3--测试实践
查看>>
espresso基础架构与API分析
查看>>
《Python语言程序设计》——2.15 本章总结
查看>>
《音乐达人秀:Adobe Audition CC实战222例》——实例5 麦克风说话和音乐播放等所有声音都混合录制...
查看>>
TIOBE 9 月编程语言排行榜,新 TIOBE 指数算法
查看>>
《Adobe Photoshop CC经典教程》—第2课2.6节使用Spot Healing Brush工具
查看>>
《AngularJS实战》——2.3 Angular中的模板
查看>>
《Node.js区块链开发》——2.5 风险提示
查看>>
《ANSYS 14热力学/电磁学/耦合场分析自学手册》——2.9 图形窗口
查看>>
阿里 MySQL 团队加入参与 WebScaleSQL 开发
查看>>
《Adobe After Effects CC经典教程》——2.3 创建新合成图像
查看>>