【笔记】最长上升子序列
2015-10-09 15:11
225 查看
题目:求一列数的最长上升子序列
O(n^2)
定义dp[i]为以num[i]结尾的最长上升子序列的长度,不难写出状态转移方程:[code]dp[i]=max{dp[i],dp[j]+1} (num[j]<num[i] j<i)
应该都会。
O(nlogn)
看上面的那个式子,可以得出dp[i]是从前i-1个中选取dp值最大的j来更新,可以优化到nlogn。定义dp[i]为 长度为i的上升子序列的末尾元素最小值,初始化dp值为INF。
这样可以不断更新num[i]到dp数组中,因为是递增的,所以可以二分查找+O(1)修改。
参考:《挑战程序设计竞赛》 && http://www.felix021.com/blog/read.php?1587
题目:codevs3955
代码:
[code]#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int size=1000010; const int INF=233333333; int num[size],dp[size]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&num[i]); dp[i]=INF; } for(int i=1;i<=n;i++) { dp[lower_bound(dp+1,dp+1+n,num[i])-dp]=num[i]; } printf("%d",lower_bound(dp+1,dp+1+n,INF)-dp-1); return 0; }
还可以这么写:
[code]#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int size=1000010; const int INF=233333333; int num[size],dp[size]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&num[i]); dp[i]=INF; } for(int i=1;i<=n;i++) { *lower_bound(dp+1,dp+1+n,num[i])=num[i]; } printf("%d",lower_bound(dp+1,dp+1+n,INF)-dp-1); return 0; }
解除引用,改变指向的地址所保存的值。
相关文章推荐
- 3.Python标准库_路径与文件 (os.path包, glob包)
- linux增加自定义path和manpath
- centos7下安装配置redis3.0.4
- Blockd的使用(定义,作用,typedef,使用场景,注意事项)
- CSS你可能还不知道的一些知识点
- ARM定制
- 亿级Web系统搭建
- 虫食算
- Windows Server时间服务器配置方法
- Java api 共享
- 使用imageloader加载图片时 修改缓存的使用的key
- 声音采集播放程序
- C++ vector基础
- C#中的线程(一)入门
- wex5关于data组件跨域返回json数据加载
- 字符数组和字符指针的区别
- linux内核代码情景分析学习笔记(一)
- 图片在线裁剪(jQuery + HttpHandler)源码
- plsql找不到tnsaName.ora文件时
- shell, python中比较两个日期的先后