zoukankan      html  css  js  c++  java
  • 二分搜索模板

     1 int bs1(int x,int y,int t) {  //二分求上界 
     2     while(x <= y) {
     3         int mid = x + (y - x) / 2;
     4         if(num[mid] <= t) x = mid + 1;
     5         else y = mid - 1;
     6     }
     7     return x;
     8 }
     9 int bs2(int x,int y,int t) { //二分求下界 
    10     while(x <= y) {
    11         int mid = x + (y - x) / 2;
    12         if(num[mid] >= t) x = mid + 1;
    13         else y = mid - 1;
    14     }
    15     return x;
    16 }
    View Code

     与之相关的有nlogn的最长上升子序列,最长下降子序列的算法

    http://blog.csdn.net/wall_f/article/details/8295812

    另外大致讲下nlogn求最长上升子序列的思想。

    其实跟背包问题里把二维数组降维的思想特别像。

    举个栗子:

    1 2 3  4  5 6

    1 2 4 10 3 5

    i先从1循环到4

    dp[1]=1; dp[2]=2; dp[3]=4; dp[4]=10; //dp数组的值代表最长上升子序列的长度,此时len=4

    当i循环到5的时候,发现dp[len]>nu[5],此时如果按照我们最直接思想是从前往后遍历一遍dp数组,找到第一个大于nu[5]的数,列出第二种情况。

    即:

    一: 1 2 4 10

    二: 1 2 3

    然后接着遍历,但要对着dp[m][n]数组进行遍历了。这个时候我们可以联想一下01背包问题降维的思路,也就是从后往前遍历dp数组,使得其无后效性。那这个其实也是一样的,我们可以发现dp[2][n]根本没有存在的必要,只需要把dp[1][3]=3即可,这样dp[1][n]d 最终的结果len不会改变(因为len是否增加,只与dp[1][len]有关),也满足了我们只遍历一个数组就可以考虑到这两种情况的需求。

    以此类推,最后其实就是遍历nu数组

    1.如果nu[i]>dp[len],dp[++len]=nu[i];

    2.否则,二分遍历dp数组,找到第一个大于nu[i]的数,用nu[i]取代它,更新数组。

    这个是我的理解,下面还有另一种理解方法,感觉讲得也很好,分享给大家。

    http://www.cnblogs.com/itlqs/p/5743114.html

  • 相关阅读:
    输出流
    异常处理
    异常限制
    多个受控异常
    跟踪异常传播
    动手动脑练习2
    动手动脑练习
    文件总结
    程序员修炼之道3
    Shell教程 之printf命令
  • 原文地址:https://www.cnblogs.com/zmin/p/7616472.html
Copyright © 2011-2022 走看看