最近一直在做《挑战程序设计竞赛》的练习题,感觉好多经典的题,都值得记录。

题意:给你t组数据,每组数组有n个数字,求每组的最长上升子序列的长度。

思路:由于n最大为40000,所以n*n的复杂度不够了,会超时。

   书上状态方程换成了d[i]——以长度为i+1的上升子序列中末尾元素的最小值。

   那么我们在遍历第i个元素时候,以这个元素为末尾元素的最长子序列也就是在d[i]中找到一个小于num[i]的最大值,然后在这个序列末尾加上num[i]

   显然,我们在查找时便可以利用二分搜索,从而把复杂度从原来的n变为了logn,总复杂度从n*n变成了nlogn

  

   d[i]已经保证了长度为i+1的上升子序列末尾元素的最小值,那么对于d[i+1]长度为i+2的子序列里面,要获得最长,自然就要从长度为i+1的子序列中,挑选末尾元素为最小的子序列后面添加元素。所以d[i+1] > d[i],d数组是一个递增的数组,所以就能用二分搜索了。

  lower_bound(d,d+n,num[i]); //默认数组d为上升数组,返回第一个大于等于num[i]的指针。
  lower_bound(d,d+n,num[i],greater<int>()); //表达数组d为下降数组,返回第一个小于等于num[i]的指针。

AC代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 40005;
const int INF = 0X3F3F3F3F;
int n,t,num[N],d[N];
//d[i] = 长度为i+1的上升子序列中末尾元素的最小值,不存在则INF
void solve()
{
for(int i = 0; i < n; i++)
d[i] = INF;
for(int i = 0; i < n; i++)
{
scanf("%d", num+i);
*lower_bound(d,d+n,num[i]) = num[i];
}
printf("%d\n", lower_bound(d,d+n,INF) - d);
}
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
solve();
}
return 0;
}

  

POJ 1631 Bridging signals DP(最长上升子序列)的更多相关文章

  1. POJ - 1631 Bridging signals(最长上升子序列---LIS)

    题意:左右各n个端口,已知n组线路,要求切除最少的线路,使剩下的线路各不相交,按照左端口递增的顺序输入. 分析: 1.设左端口为l,右端口为r,因为左端口递增输入,l[i] < l[j](i & ...

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

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

  3. poj 1631 Bridging signals (二分||DP||最长递增子序列)

    Bridging signals Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9234   Accepted: 5037 ...

  4. Poj 1631 Bridging signals(二分+DP 解 LIS)

    题意:题目很难懂,题意很简单,求最长递增子序列LIS. 分析:本题的最大数据40000,多个case.用基础的O(N^2)动态规划求解是超时,采用O(n*log2n)的二分查找加速的改进型DP后AC了 ...

  5. OpenJudge/Poj 1631 Bridging signals

    1.链接地址: http://poj.org/problem?id=1631 http://bailian.openjudge.cn/practice/1631 2.题目: Bridging sign ...

  6. POJ 1631 Bridging signals(LIS O(nlogn)算法)

    Bridging signals Description 'Oh no, they've done it again', cries the chief designer at the Waferla ...

  7. POJ 1631 Bridging signals

    Bridging signals Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9441   Accepted: 5166 ...

  8. POJ 1631 Bridging signals & 2533 Longest Ordered Subsequence

    两个都是最长上升子序列,所以就放一起了 1631 因为长度为40000,所以要用O(nlogn)的算法,其实就是另用一个数组c来存储当前最长子序列每一位的最小值,然后二分查找当前值在其中的位置:如果当 ...

  9. POJ 1631 Bridging signals(LIS 二分法 高速方法)

    Language: Default Bridging signals Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1076 ...

随机推荐

  1. Java中的XML操作

    1.DOM方式解析(读取)XML文件 待解析(读取)的XML文件,直接放在项目根目录下即可 <?xml version="1.0" encoding="UTF-8& ...

  2. Javascript:字符串分割split()妙用

    概述: split() 方法将字符串分割为字符串数组,并返回此数组 语法格式: stringObject.split(separator,limit) 参数说明: 注意:如果把空字符串 (" ...

  3. EBS OAF开发中的Java 实体对象(Entity Object)验证功能补充

    EBS OAF开发中的Java 实体对象(Entity Object)验证功能补充 (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) EO理论上 ...

  4. JavaScript获取元素样式

    原生的JavaScript获取写在标签内部的样式很简单: <div class="test" id="test" style="width:10 ...

  5. 基于JQUERY写的 LISTBOX 选择器

    本文来之于:http://blog.csdn.net/jetsteven/article/details/5104380# 1.经常用到如下图的选择器,而且要支持排序的,所以萌生用JQUERY写一个. ...

  6. iOS_SN_Xcode内存泄露调试

    用Xcode进行内存调试有两种方法: 1.静态方法 2.动态方法 静态方法是直接在Xcode的菜单栏中选择product-->analyze 如截图所示. 之后会看到Xcode的编译状态上会有如 ...

  7. UVa 679 小球下落 简单模拟题,树

    题目大意:给你一个完全二叉树,并且给他们编号,编号规则为左子树为2*k,右子树为2*k+1,每一个节点 上都有一个开关,初始时开关都处于关闭状态,小球碰到节点就会改变该点的开关的状态.然后给你I个小球 ...

  8. C语言中的memset函数和数组指针

    代码: #include <iostream> #include <cstring> using namespace std; int main(){ ] = {}; mems ...

  9. JDBC中PreparedStatement和Statement的区别

    共同点: PreparedStatement和Statement都是用来执行SQL查询语句的API之一. 不同点: 在PreparedStatement中,当我们经常需要反复执行一条结构相似的sql语 ...

  10. android单选按钮选择,RadioGroup,radioButton

    android单选按钮选择,RadioGroup,radioButton 14. 四 / android基础 / 没有评论   单选布局绑定 如何识别选择