题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1950

一直只知道有除n*n的算法之外的求LIS,但是没学过,也没见过,今天终于学了一下,dp[i]表示以a[i]为末尾的最长上升子序列的长度;

其实就是下面大神写的这样:

  1. #include<stdio.h>
  2. #include<iostream>
  3. #include<string.h>
  4. using namespace std;
  5. #define N 41000
  6. int a[N], b[N];
  7. int BiSearch(int x, int L, int R)
  8. {
  9. while(L<=R)
  10. {
  11. int mid = (L + R) >> ;
  12. if(x > b[mid])
  13. L = mid+;
  14. else
  15. R = mid-;
  16. }
  17. return L;
  18. }
  19. int main()
  20. {
  21. int T, n;
  22. scanf("%d", &T);
  23. while(T--)
  24. {
  25. scanf("%d", &n);
  26. for(int i=; i<n; i++)
  27. scanf("%d", &a[i]);
  28.  
  29. b[]=a[];
  30. int len=;
  31. for(int i=; i<n; i++)
  32. {
  33. if(a[i]>b[len-])
  34. b[len++]=a[i];
  35. else
  36. {
  37. int pos = BiSearch(a[i], , len-);
  38. ///二分找到b数组中第一个大于等于a[i]的位置的下标;
  39. ///或者用c++中的函数pos=lower_bound(a[i], b, b+len-1)-ans;
  40. b[pos] = a[i];
  41. }
  42. }
  43. printf("%d\n", len);
  44. }
  45. return ;
  46. }

源于算法书上的想法:其实都差不多;

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <cmath>
  5. #include <vector>
  6. #include <algorithm>
  7. #include <string>
  8. using namespace std;
  9.  
  10. #define N 41100
  11. #define MOD 1000000007
  12. #define met(a, b) memset(a, b, sizeof(a))
  13. #define INF 0x3f3f3f3f
  14.  
  15. typedef long long LL;
  16.  
  17. int n, m, a[N], dp[N];
  18. ///dp[i] 表示长度为i的上升子序列中末尾元素的最小值;
  19. int Binary_Search(int x, int a[], int L, int R)
  20. {
  21. while(L<=R)
  22. {
  23. int Mid = (L+R)/;
  24. if(a[Mid] < x) L = Mid+;
  25. else R = Mid-;
  26. }
  27. return L;
  28. }
  29. int main()
  30. {
  31. int T;
  32.  
  33. scanf("%d", &T);
  34.  
  35. while(T--)
  36. {
  37. met(dp, INF);
  38.  
  39. scanf("%d", &n);
  40.  
  41. for(int i=; i<=n; i++)
  42. scanf("%d", &a[i]);
  43.  
  44. int ans = ;
  45.  
  46. for(int i=; i<=n; i++)
  47. {
  48. int pos = Binary_Search(a[i], dp, , n);
  49.  
  50. dp[pos] = a[i];
  51.  
  52. ans = max(ans, pos);
  53. }
  54. printf("%d\n", ans);
  55. }
  56. return ;
  57. }

里面的那个应该是pos=lower_bound(a, a+n, x)-a;///求x在a数组中的位置;

最长递增子序列,Longest Increasing Subsequence 下面我们简记为 LIS。
排序+LCS算法 以及 DP算法就忽略了,这两个太容易理解了。

假设存在一个序列d[1..9] = 2 1 5 3 6 4 8 9 7,可以看出来它的LIS长度为5。n
下面一步一步试着找出它。
我们定义一个序列B,然后令 i = 1 to 9 逐个考察这个序列。
此外,我们用一个变量Len来记录现在最长算到多少了

首先,把d[1]有序地放到B里,令B[1] = 2,就是说当只有1一个数字2的时候,长度为1的LIS的最小末尾是2。这时Len=1

然后,把d[2]有序地放到B里,令B[1] = 1,就是说长度为1的LIS的最小末尾是1,d[1]=2已经没用了,很容易理解吧。这时Len=1

接着,d[3] = 5,d[3]>B[1],所以令B[1+1]=B[2]=d[3]=5,就是说长度为2的LIS的最小末尾是5,很容易理解吧。这时候B[1..2] = 1, 5,Len=2

再来,d[4] = 3,它正好加在1,5之间,放在1的位置显然不合适,因为1小于3,长度为1的LIS最小末尾应该是1,这样很容易推知,长度为2的LIS最小末尾是3,于是可以把5淘汰掉,这时候B[1..2] = 1, 3,Len = 2

继续,d[5] = 6,它在3后面,因为B[2] = 3, 而6在3后面,于是很容易可以推知B[3] = 6, 这时B[1..3] = 1, 3, 6,还是很容易理解吧? Len = 3 了噢。

第6个, d[6] = 4,你看它在3和6之间,于是我们就可以把6替换掉,得到B[3] = 4。B[1..3] = 1, 3, 4, Len继续等于3

第7个, d[7] = 8,它很大,比4大,嗯。于是B[4] = 8。Len变成4了

第8个, d[8] = 9,得到B[5] = 9,嗯。Len继续增大,到5了。

最后一个, d[9] = 7,它在B[3] = 4和B[4] = 8之间,所以我们知道,最新的B[4] =7,B[1..5] = 1, 3, 4, 7, 9,Len = 5。

于是我们知道了LIS的长度为5。

!!!!! 注意。这个1,3,4,7,9不是LIS,它只是存储的对应长度LIS的最小末尾。有了这个末尾,我们就可以一个一个地插入数据。虽然最后一个d[9] = 7更新进去对于这组数据没有什么意义,但是如果后面再出现两个数字 8 和 9,那么就可以把8更新到d[5], 9更新到d[6],得出LIS的长度为6。

然后应该发现一件事情了:在B中插入数据是有序的,而且是进行替换而不需要挪动——也就是说,我们可以使用二分查找,将每一个数字的插入时间优化到O(logN)~~~~~于是算法的时间复杂度就降低到了O(NlogN)~!

Bridging signals---hdu1950(最长上升子序列复杂度n*log(n) )的更多相关文章

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

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

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

    最近一直在做<挑战程序设计竞赛>的练习题,感觉好多经典的题,都值得记录. 题意:给你t组数据,每组数组有n个数字,求每组的最长上升子序列的长度. 思路:由于n最大为40000,所以n*n的 ...

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

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

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

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

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

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

  6. 最长上升子序列(LIS)的n*log(n)求法

    方法: 对于某个序列,设一个数组,将序列第一个数放入,然后再一个一个判断序列下一位,如果大于当前数组的末尾元素,则加入数组,否则利用二分法找到第一个大于等于当前数的元素并替换,最后这个数组的长度len ...

  7. hdu1950 最长上升子序列nlogn

    简单. #include<cstdio> #include<cstring> #include<iostream> using namespace std; ; i ...

  8. 最长递增子序列(lis)最长公共子序列(lcs) 最长公共上升子序列(lics)

    lis: 复杂度nlgn #include<iostream> #include<cstdio> using namespace std; ],lis[],res=; int ...

  9. 最长上升子序列(LIS)与最长公共子序列(LCS)

    1.LIS : 给定一个序列,求它的最长上升子序列(n<=2000) 第一种 O(n^2): dp[i] 为以i为开头的最长上升子序列长度 code1: #include<cstdio&g ...

随机推荐

  1. iTween基础之Shake(摆动)

    一.基础介绍:二.基础属性 原文地址 :http://blog.csdn.net/dingkun520wy/article/details/50836780 一.基础介绍 ShakePosition: ...

  2. 【每日scrum】NO.5

    尝试采用自己的地图,绘点并计算路径,但是地图打开出现问题.

  3. xcode 使用通用总结

    一.搜索东西 有时候类很多,方法很多,想改某类时,还要打开各自文件夹去点进去,感觉很麻烦费时间. 如下图:用此搜索可以搜到此类,从而进行修改. 有时候想在类中找某个方法或者属性,自已一点一点找很费劲, ...

  4. Careercup - Google面试题 - 6253551042953216

    2014-05-06 01:49 题目链接 原题: Modify the following code to add a row number for each line is printed pub ...

  5. Entity Framework技术导游系列开篇与热身

    在微软平台写程序有年头了,随着微软数据存取技术的持续演化,我在程序中先后使用过ODBC.DAO.ADO.ADO.NET.LINQ to SQL. Entity Framework这些技术. 近几年来, ...

  6. 【BZOJ】【3164】【HEOI2013】Eden的博弈问题

    树形DP 这题在考场上直接写的TreeDP……当时也没想出一个像样的暴力来对拍……好像只能这么直接做了……? 都说是博弈树了,转移关系都给的这么直接了……也没啥难度了吧= =(怪不得大家都不愿意写题解 ...

  7. PHP soap Web Service 使用SoapDiscovery.class.php 生成wsdl文件

    PHP soap web service 使用wsdl文件 demo: ============================================================== 服 ...

  8. ASP.NET页面优化性能提升方法记录

    今天与大家分享:一种优化页面执行速度的方法.采用这个方法,可以使用页面的执行速度获得[8倍]的提升效果. 为了让您对优化的效果有个直观的了解,我准备了下面的测试结果截图: 测试环境:1. Window ...

  9. 【二】php常用方法

    -------------------------------数据类型------------------------------------------ 1.settype(var,type)  类 ...

  10. 一道有趣的javascript编程题

    题目:实现以下功能 1. 点击按钮“打开新窗口”,打开新的子页面,要求新窗口的大小为400px X 200px 2. 输入地址信息,点击“确定”按钮,关闭该页面 3. 将子页面中输入的地址信息,回传到 ...