zoukankan      html  css  js  c++  java
  • LIS的优化

    二分优化

    在求一个最长不上升自序列中,显然其结尾元素越小,越有利于接其他元素,对答案的贡献也就可能会更高

    那么我们可以用low[i]去存长度为i的LIS结尾元素的最小值

    因此我们只要维护low数组

    对于每一个a[ i ],如果a[ i ] > low [当前最长的LIS长度],就把 a [ i ]接到当前最长的LIS后面,即low [++当前最长的LIS长度] = a [ i ]。

    那么,怎么维护 low 数组呢?
    对于每一个a [ i ],如果a [ i ]能接到 LIS 后面,就接上去;否则,就用 a [ i ] 取更新 low 数组。具体方法是,在low数组中找到第一个大于等于a [ i ]的元素low [ j ],用a [ i ]去更新 low [ j ]。如果从头到尾扫一遍 low 数组的话,时间复杂度仍是O(n^2)。我们注意到 low 数组内部一定是单调不降的,所有我们可以二分 low 数组,找出第一个大于a[ i ]的元素。二分一次 low 数组的时间复杂度的O(lgn),所以总的时间复杂度是O(nlogn)。

    例题

    P2782 友好城市

    先将所有城市排序,然后发现就是一个最长不下降子序列

    但暴力只能拿50pts

     1 /*
     2 Work by: Suzt_ilymics
     3 Knowledge: ??
     4 Time: O(??)
     5 */
     6 #include<iostream>
     7 #include<cstdio>
     8 #include<algorithm>
     9 using namespace std;
    10 const int MAXN = 2e5+5;
    11 struct good{
    12     int n,s;
    13     bool operator < (const good &b) const {return n == b.n ? s < b.s : n < b.n; }
    14 }a[MAXN];
    15 int n, ans;
    16 int f[MAXN];
    17 int main()
    18 {
    19     scanf("%d", &n);
    20     for(int i = 1; i <= n; ++i){
    21         scanf("%d%d", &a[i].n, &a[i].s);
    22     }
    23     
    24     sort(a+1, a+n+1);
    25     
    26     for(int i = 1; i <= n; ++i){
    27         f[i] = 1;
    28         for(int j = 1; j < i; ++j){
    29             if(a[j].n < a[i].n && a[j].s < a[i].s){
    30                 f[i] = max(f[i], f[j] + 1);
    31             }
    32         }
    33         ans = max(ans, f[i]);
    34     }
    35     
    36     printf("%d", ans);
    37     
    38     return 0;
    39 }

    考虑一下上面的优化,因为北岸的城市是排好的,所以low数组里只需存南岸

     1 /*
     2 Work by: Suzt_ilymics
     3 Knowledge: LIS + 二分优化 
     4 Time: O(nlogn)
     5 */
     6 #include<iostream>
     7 #include<cstdio>
     8 #include<algorithm>
     9 #define INF 2100000000
    10 using namespace std;
    11 const int MAXN = 2e5+5;
    12 struct good{
    13     int n,s;
    14     bool operator < (const good &b) const {return n == b.n ? s < b.s : n < b.n; }
    15 }a[MAXN];
    16 int n, ans;
    17 int f[MAXN], low[MAXN];
    18 
    19 int ef(int r, int k){    
    20     int mid, l = 0;
    21     while(l <= r){
    22         mid = (l + r) >> 1;
    23         if(low[mid] <= k){
    24             l = mid + 1;
    25         }
    26         else{
    27             r = mid - 1;
    28         }
    29     }
    30     return l;
    31 }
    32 
    33 int main()
    34 {
    35     scanf("%d", &n);
    36     for(int i = 1; i <= n; ++i){
    37         scanf("%d%d", &a[i].n, &a[i].s);
    38         low[i] = INF;
    39     }
    40     
    41     sort(a+1, a+n+1);
    42     
    43     low[1] = a[1].s;
    44     ans = 1;
    45     
    46     for(int i = 2; i <= n; ++i){
    47         if(a[i].s > low[ans]){
    48             low[++ans] = a[i].s;
    49         }
    50         else{
    51             low[ ef(ans, a[i].s) ] = a[i].s;
    52         }
    53     }
    54     
    55     printf("%d", ans);
    56     
    57     return 0;
    58 }
  • 相关阅读:
    DetachedCriteria的使用
    Windows 9立即公布了
    加壳学习笔记(三)-简单的脱壳思路&amp;调试思路
    用异或来交换两个变量能提快速度是错误的
    珍爱生命,举手之劳__怎样优雅的叫优步专车
    【翻译自mos文章】使用aum( Automatic Undo Management) 时遇到 ORA-01555错误--- 原因和解决方式。
    HDU 5311 Hidden String (优美的暴力)
    ChargeSystem——One,Two,Three
    GCC编译uboot出现(.ARM.exidx+0x0): undefined reference to `__aeabi_unwind_cpp_pr0&#39;错误的解决的方法
    java中commons-beanutils的介绍
  • 原文地址:https://www.cnblogs.com/Silymtics/p/13852302.html
Copyright © 2011-2022 走看看