HDU 1950 Bridging signals(LIS)
最长上升子序列(LIS)的典型变形,O(n^2)的动归会超时。LIS问题可以优化为nlogn的算法。
定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则记录最小的那个最末元素。
注意d中元素是单调递增的,下面要用到这个性质。
首先len = 1,d[1] = a[1],然后对a[i]:若a[i]>d[len],那么d[++len] = a[i];
否则,我们要从d[1]到d[len-1]中找到一个j,满足d[j-1]<a[i]<d[j],则根据d的定义,我们需要更新长度为j的上升子序列的最末元素(使之为最小的)即 d[j] = a[i];
最终答案就是len
利用d的单调性,在查找j的时候可以二分查找,从而时间复杂度为nlogn。
==================================
最长递增子序列,Longest Increasing Subsequence 下面我们简记为 LIS。
假设存在一个序列a[1..9] = 2 1 5 3 6 4 8 9 7,可以看出来它的LIS长度为5(1,3,4,8,9)。n
下面一步一步试着找出它。
我们定义一个序列d,然后令 i = 1 to 9 逐个考察这个序列。
此外,我们用一个变量Len来记录现在最长算到多少了
首先,把a[1]有序地放到d里,令d[1] = 2,就是说当只有1一个数字2的时候,长度为1的LIS的最小末尾是2。这时Len=1
然后,把a[2]有序地放到d里,因为1<2,就是说长度为1的LIS的最小末尾是1,所以d[1]=2已经没用了,即d[1]=1,很容易理解吧。这时Len=1
然后,a[3] = 5,a[3]>d[1],所以d[1+1]=d[2]=a[3]=5,就是说长度为2的LIS的最小末尾是5,很容易理解吧。这时候d[1..2] = 1, 5。这时Len=2
然后,a[4] = 3,它正好加在1,5之间,放在1的位置显然不合适,因为1小于3,长度为1的LIS最小末尾应该是1,这样很容易推知,
长度为2的LIS最小末尾是3,于是可以把5淘汰掉,这时候d[1..2]=1,3。这时Len=2
第5个,a[5] = 6,它在3后面,因为d[2] = 3, 而6在3后面,于是很容易可以推知d[3] = 6, 这时d[1..3] = 1,3,6。这时Len=3
第6个, a[6] = 4,你看它在3和6之间,于是我们就可以把6替换掉,得到d[3] = 4。d[1..3] = 1,3,4。这时Len=3
第7个, a[7] = 8,它很大,比4大,嗯。于是d[4]=8。这时len=4
第8个, a[8] = 9,得到d[5]=9,嗯。这时len=5
最后一个, a[9] = 7,它在d[3]=4和d[4] = 8之间,所以我们知道,最新的d[4] =7,d[1..5] = 1,3,4,7,9。这时Len=5。
于是我们知道了LIS的长度为5。
!!!!! 注意。这个1,3,4,7,9不是LIS,它只是存储的对应长度LIS的最小末尾。有了这个末尾,我们就可以一个一个地插入数据。虽然最后一个a[9] = 7更新进去对于这组数据没有什么意义,但是如果后面再出现两个数字 8 和 9,那么就可以把8更新到d[5], 9更新到d[6],得出LIS的长度为6。
然后应该发现一件事情了:在d中插入数据是有序的,而且是进行替换而不需要挪动——也就是说,我们可以使用二分查找,将每一个数字的插入时间优化到O(logN)~~~~~于是算法的时间复杂度就降低到了O(NlogN)~!
#include<cstdio>
#include<algorithm>
using namespace std;
int a[],d[],len;
int binary_search(int i){
int l=,r=len;
while(l<r){
int mid=l+(r-l)/;
if(d[mid]>=a[i]) r=mid;
else l=mid+;
}
return l;
}
int main()
{
int n,p;
scanf("%d",&n);
while(n--){
scanf("%d",&p);
for(int i=;i<=p;i++)
scanf("%d",&a[i]);
d[]=a[],len=;
for(int i=;i<=p;i++){
if(a[i]>d[len])
d[++len]=a[i];
else{//也可以使用库函数lower_bound()
int pos=binary_search(i);//int pos=lower_bound(d,d+len,a[i])-d;
d[pos]=a[i];
}
}
printf("%d\n",len);
}
}
HDU 1950 Bridging signals(LIS)的更多相关文章
- HDU 1950 Bridging signals【最长上升序列】
解题思路:题目给出的描述就是一种求最长上升子序列的方法 将该列数an与其按升序排好序后的an'求出最长公共子序列就是最长上升子序列 但是这道题用这种方法是会超时的,用滚动数组优化也超时, 下面是网上找 ...
- hdu 1950 Bridging signals 求最长子序列 ( 二分模板 )
Bridging signals Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- HDU 1950 Bridging signals (DP)
职务地址:HDU 1950 这题是求最长上升序列,可是普通的最长上升序列求法时间复杂度是O(n*n).显然会超时.于是便学了一种O(n*logn)的方法.也非常好理解. 感觉还用到了一点贪心的思想. ...
- HDU 1950 Bridging signals (LIS,O(nlogn))
题意: 给一个数字序列,要求找到LIS,输出其长度. 思路: 扫一遍+二分,复杂度O(nlogn),空间复杂度O(n). 具体方法:增加一个数组,用d[i]表示长度为 i 的递增子序列的最后一个元素, ...
- HDU 1950 Bridging signals
那么一大篇的题目描述还真是吓人. 仔细一读其实就是一个LIS,还无任何变形. 刚刚学会了个二分优化的DP,1A无压力. //#define LOCAL #include <iostream> ...
- hdoj 1950 Bridging signals【二分求最大上升子序列长度】【LIS】
Bridging signals Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- (hdu)1950 Bridging signals(最长上升子序列)
Problem Description 'Oh no, they've done it again', cries the chief designer at the Waferland chip f ...
- POJ 1631 Bridging signals (LIS:最长上升子序列)
题意:给你一个长为n(n<=40000)的整数序列, 要你求出该序列的最长上升子序列LIS. 思路:要求(nlogn)解法 令g[i]==x表示当前遍历到的长度为i的所有最长上升子序列中的最小序 ...
- HDU 1950(LIS)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1950 Bridging signals Time Limit: 5000/1000 MS (Java ...
随机推荐
- html的a标签的 href 和 onclick。
主要用于给超链接添加点击事件. aa.html <html> <body> <span>this si</span> </body> < ...
- STL容器:deque双端队列学习
所谓deque,是"double-ended queue"的缩写; 它是一种动态数组形式,可以向两端发展,在尾部和头部插入元素非常迅速; 在中间插入元素比较费时,因为需要移动其它元 ...
- 你真的搞懂ES6模块的导入导出规则了吗
前言 模块作为ES6规范的核心部分之一,在实际项目开发中经常会看到它的身影,那么我们是否真正了解它的相关规则呢,今天就带大家一起了解一下模块的导入导出规则 导入 ES6模块的导入(即import)大致 ...
- Ubuntu执行su后输入密码结果认证失败--解决办法:sudo passwd修改命令
- JSP小例子——实现用户登录小例子(不涉及DB操作)
实现用户登录小例子用户名和密码都为"admin",登陆成功使用服务器内部转发到login_success.jsp页面,并且提示登陆成功的用户名.如果登陆失败则请求重定向到login ...
- zoj3686(线段树的区间更新)
对线段树的区间更新有了初步的了解... A Simple Tree Problem Time Limit: 3 Seconds Memory Limit: 65536 KB Given a ...
- 【BZOJ4808/3175】马/[Tjoi2013]攻击装置 最小割
[BZOJ4808]马 Description 众所周知,马后炮是中国象棋中很厉害的一招必杀技."马走日字".本来,如果在要去的方向有别的棋子挡住(俗称"蹩马腿" ...
- 用httpclient做压力测试时Too many open files的解决办法
在工作过程中,用httpclient去压测一个web api,发现压一小段时间就出现了Too many open files.实际上,HttpClient建立Socket时 ,post.release ...
- SaltStack配置管理-LAMP状态设计
上一篇:SaltStack之Salt-ssh 配置文件模板 apache: pkg.installed: - name: httpd service.running: - name: httpd /e ...
- CH5105 Cookies【贪心】【线性dp】
5105 Cookies 0x50「动态规划」例题 描述 圣诞老人共有M个饼干,准备全部分给N个孩子.每个孩子有一个贪婪度,第 i 个孩子的贪婪度为 g[i].如果有 a[i] 个孩子拿到的饼干数比第 ...