最长子序列问题(二分+贪心nlogn算法)
【题目描述】
给定N个数,求这N个数的最长上升子序列的长度。
【样例输入】
7
2 5 3 4 1 7 6
【样例输出】
4
什么是最长上升子序列? 就是给你一个序列,请你在其中求出一段不断严格上升的部分,它不一定要连续。
就像这样:2,3,4,7和2,3,4,6就是序列2 5 3 4 1 7 6的两种选取方案。最长的长度是4.
什么是最长上升子序列? 就是给你一个序列,请你在其中求出一段不断严格上升的部分,它不一定要连续。
就像这样:2,3,4,7和2,3,4,6就是序列2 5 3 4 1 7 6的两种选取方案。最长的长度是4.
思路:
新建一个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)。
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn =300003,INF=0x7f7f7f7f;
int low[maxn],a[maxn];
int n,ans;
int binary_search(int *a,int r,int x)
//二分查找,返回a数组中第一个>=x的位置
{
int l=1,mid;
while(l<=r)
{
mid=(l+r)>>1;
if(a[mid]<=x)
l=mid+1;
else
r=mid-1;
}
return l;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
low[i]=INF;//由于low中存的是最小值,所以low初始化为INF
}
low[1]=a[1];
ans=1;//初始时LIS长度为1
for(int i=2;i<=n;i++)
{
if(a[i]>=low[ans])//若a[i]>=low[ans],直接把a[i]接到后面
low[++ans]=a[i];
else //否则,找到low中第一个>=a[i]的位置low[j],用a[i]更新low[j]
low[binary_search(low,ans,a[i])]=a[i];
}
printf("%d\n",ans);//输出答案
return 0;
}
最长子序列问题(二分+贪心nlogn算法)的更多相关文章
- hdu 1950 Bridging signals 求最长子序列 ( 二分模板 )
Bridging signals Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- 最长不下降序列nlogn算法
显然n方算法在比赛中是没有什么用的(不会这么容易就过的),所以nlogn的算法尤为重要. 分析: 开2个数组,一个a记原数,f[k]表示长度为f的不下降子序列末尾元素的最小值,tot表示当前已知的最长 ...
- 算法-最长子序列和C/C++实现(三个复杂度)
最长子序列和的问题非常easy: 就是一个数组,求出当中当中连续的某一段和,而这一段和是全部的连续段和的最大的值.求出这个值. 先说复杂度最高的:O(n3) 直接上代码,非常easy的: // // ...
- nyoj 17-单调递增最长子序列 && poj 2533(动态规划,演算法)
17-单调递增最长子序列 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:21 submit:49 题目描述: 求一个字符串的最长递增子序列的长度 如 ...
- 算法:Common Subsequence(动态规划 Java 最长子序列)
Description A subsequence of a given sequence is the given sequence with some elements (possible non ...
- 最长上升子序列O(nlogn)算法详解
最长上升子序列 时间限制: 10 Sec 内存限制:128 MB 题目描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.我们想知道此时最长上升子 ...
- 最长不下降子序列nlogn算法详解
今天花了很长时间终于弄懂了这个算法……毕竟找一个好的讲解真的太难了,所以励志我要自己写一个好的讲解QAQ 这篇文章是在懂了这个问题n^2解决方案的基础上学习. 解决的问题:给定一个序列,求最长不下降子 ...
- POJ 1631 Bridging signals(LIS O(nlogn)算法)
Bridging signals Description 'Oh no, they've done it again', cries the chief designer at the Waferla ...
- 最长上升子序列(LIS)长度的O(nlogn)算法
最长上升子序列(LIS)的典型变形,熟悉的n^2的动归会超时.LIS问题可以优化为nlogn的算法.定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则记录最小的那个最末元素 ...
随机推荐
- python之特殊方法
特殊方法的定义: 1.定义在某些class当中 2.不需要直接调用 3.Python的某些函数或者是操作符会调用相应的特殊方法 特殊方法很多,我们只需要编写用到的特殊方法,以及有关联性的特殊方法. — ...
- JAVA基础知识总结13(同步)
好处:解决了线程安全问题. 弊端:相对降低性能,因为判断锁需要消耗资源,还容易产生了死锁. 定义同步是有前提的: 1,必须要有两个或者两个以上的线程,才需要同步. 2,多个线程必须保证使用的是同一个锁 ...
- 读书笔记<深入理解JVM>01 关于OutOfMemoryError 堆空间的溢出
代码片段如下: package com.gosaint.shiro; import java.util.ArrayList; import java.util.List; public class H ...
- ROS探索总结(四)——简单的机器人仿真
前边我们已经介绍了ROS的基本情况,以及新手入门ROS的初级教程,现在就要真正的使用ROS进入机器人世界了.接下来我们涉及到的很多例程都是<ROS by Example>这本书的内容,我是 ...
- mysql sequelize 聚合
User.findAll({attributes: [[sequelize.fn('COUNT', sequelize.col('*')), 'email']],raw: true }).then(f ...
- 业务逻辑:shiro框架的功能实现
思路:分别在web.xml配置过滤器以及在applicationContext.xml去配置 实现步骤:1.在pom.xml里引入shiro的坐标 2.在web.xml里配置shiro过滤器 3.在a ...
- PCL—点云滤波(基于点云频率) 低层次点云处理
博客转载自:http://www.cnblogs.com/ironstark/p/5010771.html 1.点云的频率 今天在阅读分割有关的文献时,惊喜的发现,点云和图像一样,有可能也存在频率的概 ...
- Boost中实现线程安全
博客转载自: http://www.cnblogs.com/lvdongjie/p/4447142.html 1 boost原子变量和线程 #include <boost/thread.hpp& ...
- python sort、sorted、reverse、reverd的区别
sort.sorted.reverse.reversed的区别 !!! error 首先应该区分的是,sort和reverse是列表的一个方法.字符串.元组.字典.集合是没有这两个方法的.而sorte ...
- 《Maven实战》笔记-6-maven测试
一.基于Maven的测试 1.maven-surefire-plugin插件 该插件的test目标会自动执行测试源码路径(默认src/test/java)下符合以下命名模式的测试类: 以Test开头或 ...