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

  • 相关阅读:
    POJ 2923 Relocation (状态压缩,01背包)
    HDU 2126 Buy the souvenirs (01背包,输出方案数)
    hdu 2639 Bone Collector II (01背包,求第k优解)
    UVA 562 Dividing coins (01背包)
    POJ 3437 Tree Grafting
    Light OJ 1095 Arrange the Numbers(容斥)
    BZOJ 1560 火星藏宝图(DP)
    POJ 3675 Telescope
    POJ 2986 A Triangle and a Circle
    BZOJ 1040 骑士
  • 原文地址:https://www.cnblogs.com/zmin/p/7616472.html
Copyright © 2011-2022 走看看