最长上升子序列(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。
==================================

最长上升子序列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)的更多相关文章

  1. HDU 1950 Bridging signals【最长上升序列】

    解题思路:题目给出的描述就是一种求最长上升子序列的方法 将该列数an与其按升序排好序后的an'求出最长公共子序列就是最长上升子序列 但是这道题用这种方法是会超时的,用滚动数组优化也超时, 下面是网上找 ...

  2. hdu 1950 Bridging signals 求最长子序列 ( 二分模板 )

    Bridging signals Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  3. HDU 1950 Bridging signals (DP)

    职务地址:HDU 1950 这题是求最长上升序列,可是普通的最长上升序列求法时间复杂度是O(n*n).显然会超时.于是便学了一种O(n*logn)的方法.也非常好理解. 感觉还用到了一点贪心的思想. ...

  4. HDU 1950 Bridging signals (LIS,O(nlogn))

    题意: 给一个数字序列,要求找到LIS,输出其长度. 思路: 扫一遍+二分,复杂度O(nlogn),空间复杂度O(n). 具体方法:增加一个数组,用d[i]表示长度为 i 的递增子序列的最后一个元素, ...

  5. HDU 1950 Bridging signals

    那么一大篇的题目描述还真是吓人. 仔细一读其实就是一个LIS,还无任何变形. 刚刚学会了个二分优化的DP,1A无压力. //#define LOCAL #include <iostream> ...

  6. hdoj 1950 Bridging signals【二分求最大上升子序列长度】【LIS】

    Bridging signals Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  7. (hdu)1950 Bridging signals(最长上升子序列)

    Problem Description 'Oh no, they've done it again', cries the chief designer at the Waferland chip f ...

  8. POJ 1631 Bridging signals (LIS:最长上升子序列)

    题意:给你一个长为n(n<=40000)的整数序列, 要你求出该序列的最长上升子序列LIS. 思路:要求(nlogn)解法 令g[i]==x表示当前遍历到的长度为i的所有最长上升子序列中的最小序 ...

  9. HDU 1950(LIS)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1950 Bridging signals Time Limit: 5000/1000 MS (Java ...

随机推荐

  1. html的a标签的 href 和 onclick。

    主要用于给超链接添加点击事件. aa.html <html> <body> <span>this si</span> </body> < ...

  2. STL容器:deque双端队列学习

    所谓deque,是"double-ended queue"的缩写; 它是一种动态数组形式,可以向两端发展,在尾部和头部插入元素非常迅速; 在中间插入元素比较费时,因为需要移动其它元 ...

  3. 你真的搞懂ES6模块的导入导出规则了吗

    前言 模块作为ES6规范的核心部分之一,在实际项目开发中经常会看到它的身影,那么我们是否真正了解它的相关规则呢,今天就带大家一起了解一下模块的导入导出规则 导入 ES6模块的导入(即import)大致 ...

  4. Ubuntu执行su后输入密码结果认证失败--解决办法:sudo passwd修改命令

  5. JSP小例子——实现用户登录小例子(不涉及DB操作)

    实现用户登录小例子用户名和密码都为"admin",登陆成功使用服务器内部转发到login_success.jsp页面,并且提示登陆成功的用户名.如果登陆失败则请求重定向到login ...

  6. zoj3686(线段树的区间更新)

    对线段树的区间更新有了初步的了解... A Simple Tree Problem Time Limit: 3 Seconds      Memory Limit: 65536 KB Given a ...

  7. 【BZOJ4808/3175】马/[Tjoi2013]攻击装置 最小割

    [BZOJ4808]马 Description 众所周知,马后炮是中国象棋中很厉害的一招必杀技."马走日字".本来,如果在要去的方向有别的棋子挡住(俗称"蹩马腿" ...

  8. 用httpclient做压力测试时Too many open files的解决办法

    在工作过程中,用httpclient去压测一个web api,发现压一小段时间就出现了Too many open files.实际上,HttpClient建立Socket时 ,post.release ...

  9. SaltStack配置管理-LAMP状态设计

    上一篇:SaltStack之Salt-ssh 配置文件模板 apache: pkg.installed: - name: httpd service.running: - name: httpd /e ...

  10. CH5105 Cookies【贪心】【线性dp】

    5105 Cookies 0x50「动态规划」例题 描述 圣诞老人共有M个饼干,准备全部分给N个孩子.每个孩子有一个贪婪度,第 i 个孩子的贪婪度为 g[i].如果有 a[i] 个孩子拿到的饼干数比第 ...