最长递增子序列(O(nlogn))
2015-08-15 10:23
232 查看
使用最基础的方法计算最长递增子序列的时间复杂度为O(n^2),
在n值过大时,肯定会超时。因此,在这里介绍一种优化算法。
维护一个一维数组dp,dp[i]表示最长上升子序列长度是i的所有子串中末尾最小的那个数,根据这个数字,我们可以比较知道,只要当前考察的这个数比dp[i]大,那么当前这个数一定能通过dp[i]构成一个长度为i+1的上升子序列。当然我们希望在dp数组中找一个尽量靠后的数字,这样我们得到的上升子串的长度最长,查找的时候使用二分搜索,这样时间复杂度便下降了。
可能解释的不太好,那么还是把代码发出来吧
Talk is cheap,show me the code.
在n值过大时,肯定会超时。因此,在这里介绍一种优化算法。
维护一个一维数组dp,dp[i]表示最长上升子序列长度是i的所有子串中末尾最小的那个数,根据这个数字,我们可以比较知道,只要当前考察的这个数比dp[i]大,那么当前这个数一定能通过dp[i]构成一个长度为i+1的上升子序列。当然我们希望在dp数组中找一个尽量靠后的数字,这样我们得到的上升子串的长度最长,查找的时候使用二分搜索,这样时间复杂度便下降了。
可能解释的不太好,那么还是把代码发出来吧
Talk is cheap,show me the code.
#include<iostream> #include<stdio.h> #include<queue> #include<stack> #include<algorithm> #include<string.h> #include<string> #include<math.h> int num[40005]; int dp[40005]; using namespace std; int main() { int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&num[i]); } int len=1; dp[1]=num[1]; for(int i=2;i<=n;i++) { if(num[i]>dp[len]) { len++; dp[len]=num[i]; continue; } int pos=lower_bound(dp+1,dp+len+1,num[i])-dp; dp[pos]=num[i]; } printf("%d\n",len); } return 0; }
相关文章推荐
- Java中P 4000 reparedStatement和Statement的用法区别
- java使用httpclient简单模拟登陆微信公众开放平台
- python sort和sorted使用详解
- Win8运行程序的时候总是提示内置管理员无法激活应用该怎么办?
- 九度oj 1033
- 二分匹配 HDU1281 棋盘游戏
- 俄罗斯方块学习视频
- 分区表简单介绍
- 进程间通信简介(IPC)--《linux/unix系统编程手册》
- PHP Mysqli 常用方法集合
- diff命令详解
- C++ Primer 学习笔记与思考_5 bitset你用的正确吗?
- Java基础04 封装与接口
- POJ 1739
- 没有SQL Server数据库时如何打开.MDF文件
- Codeforces Round #316 (Div. 2) B. Simple Game
- 利用Shell脚本进行文件内容去重
- hdu 3295 An interesting mobile game(bfs)
- 磁保持继电器动作原理分析
- java基础复习