• 最长上升子序列的两种解法


    常规思路:

    定义 dp[i]:=以a[i]为末尾元素的最长上升子序列的长度,

    以a[i]结尾的上升序列是:

    只包含a[i]的序列,

    在满足j<i并且aj<ai的以aj为末尾的上升子序列末尾追加上ai得到的子序列。

    两者之一。

    这样递推关系:dp[i]=max(1,dp[j]+1|j<i&&a[j]<a[i])   就能在O(n^2)的时间内解决问题.

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <vector>
     5 #include <cstring>
     6 #include <string>
     7 #include <algorithm>
     8 #include <string>
     9 #include <set>
    10 #include <functional>
    11 #include <numeric>
    12 #include <sstream>
    13 #include <stack>
    14 #include <map>
    15 #include <queue>
    16 #pragma comment(linker, "/STACK:102400000,102400000")
    17 #define CL(arr, val)    memset(arr, val, sizeof(arr))
    18 
    19 #define ll long long
    20 #define inf 0x7f7f7f7f
    21 #define lc l,m,rt<<1
    22 #define rc m + 1,r,rt<<1|1
    23 #define pi acos(-1.0)
    24 
    25 #define L(x)    (x) << 1
    26 #define R(x)    (x) << 1 | 1
    27 #define MID(l, r)   (l + r) >> 1
    28 #define Min(x, y)   (x) < (y) ? (x) : (y)
    29 #define Max(x, y)   (x) < (y) ? (y) : (x)
    30 #define lson l,m,rt<<1
    31 #define rson m+1,r,rt<<1|1
    32 #define E(x)        (1 << (x))
    33 #define iabs(x)     (x) < 0 ? -(x) : (x)
    34 #define OUT(x)  printf("%I64d
    ", x)
    35 #define lowbit(x)   (x)&(-x)
    36 #define Read()  freopen("a.txt", "r", stdin)
    37 #define Write() freopen("b.txt", "w", stdout);
    38 #define maxn 100010
    39 #define mod 1000000007
    40 using namespace std;
    41 int a[1001],dp[1001];
    42 int n;
    43 void solve()
    44 {
    45     int res=0;
    46     memset(dp,0,sizeof(dp));
    47     for(int i=0;i<n;i++)
    48     {
    49         dp[i]=1;
    50         for(int j=0;j<i;j++)
    51         {
    52             if(a[i]>a[j])
    53             {
    54                 dp[i]=max(dp[i],dp[j]+1);
    55             }
    56         }
    57         res=max(dp[i],res);
    58     }
    59     printf("%d
    ",res);
    60 }
    61 int main()
    62 {
    63     //freopen("a.txt","r",stdin);
    64     scanf("%d",&n);
    65     for(int i=0;i<n;i++)scanf("%d",&a[i]);
    66     solve();
    67     return 0;
    68 }

    但是如果重新定义递推关系:

    dp[i]:=长度为i+1的上升子序列中末尾元素的最小值(不存在就是INF) 

    最开始dp[i]的值都初始化为INF,然后由前到后考虑数列的元素,对于每个aj,如果i==0或者dp[i-1]<a[j]的话,就有dp[i]=min(dp[i],aj)进行更新,最终找出使得

    dp[i]<INF的最大i+1就是结果,之间实现也是O(n^2)的复杂度,但是还可以进一步优化.

    首先dp数列中除INF外是单调递增的,所以可以知道对于每个aj最多只需要一次更新,对于这次更新究竟在什么位置,不必每个遍历,二分搜索就行.

    复杂度为O(nlogn).

    low_bound函数从已经排好序的序列a中利用二分搜索出指向ai>=k的ai的最小的指针,

    upper_bound指向满足ai>k的ai的最小指针。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <vector>
     5 #include <cstring>
     6 #include <string>
     7 #include <algorithm>
     8 #include <string>
     9 #include <set>
    10 #include <functional>
    11 #include <numeric>
    12 #include <sstream>
    13 #include <stack>
    14 #include <map>
    15 #include <queue>
    16 #pragma comment(linker, "/STACK:102400000,102400000")
    17 #define CL(arr, val)    memset(arr, val, sizeof(arr))
    18 
    19 #define ll long long
    20 #define inf 0x7f7f7f7f
    21 #define lc l,m,rt<<1
    22 #define rc m + 1,r,rt<<1|1
    23 #define pi acos(-1.0)
    24 
    25 #define L(x)    (x) << 1
    26 #define R(x)    (x) << 1 | 1
    27 #define MID(l, r)   (l + r) >> 1
    28 #define Min(x, y)   (x) < (y) ? (x) : (y)
    29 #define Max(x, y)   (x) < (y) ? (y) : (x)
    30 #define lson l,m,rt<<1
    31 #define rson m+1,r,rt<<1|1
    32 #define E(x)        (1 << (x))
    33 #define iabs(x)     (x) < 0 ? -(x) : (x)
    34 #define OUT(x)  printf("%I64d
    ", x)
    35 #define lowbit(x)   (x)&(-x)
    36 #define Read()  freopen("a.txt", "r", stdin)
    37 #define Write() freopen("b.txt", "w", stdout);
    38 #define maxn 100010
    39 #define mod 1000000007
    40 using namespace std;
    41 int a[50001],dp[50001];
    42 int n;
    43 void solve()
    44 {
    45     for(int i=0;i<n;i++) dp[i]=inf;
    46     for(int i=0;i<n;i++)
    47     {
    48         *lower_bound(dp,dp+n,a[i]) = a[i];
    49     }
    50     printf("%d
    ",lower_bound(dp,dp+n,inf)-dp);
    51 }
    52 int main()
    53 {
    54     //freopen("a.txt","r",stdin);
    55     scanf("%d",&n);
    56     for(int i=0;i<n;i++)scanf("%d",&a[i]);
    57     solve();
    58     return 0;
    59 }
  • 相关阅读:
    PHP 命名空间
    使用 htaccess 重写 url,隐藏查询字符串
    HTML 长文本换行
    Mac OS X 上的Apache配置
    无法debug断点跟踪JDK源代码——missing line number attributes的解决方法
    根据多条件删除还能这样写
    wm_concat()函数
    spring 事务-使用@Transactional 注解(事务隔离级别)
    spring 中常用的两种事务配置方式以及事务的传播性、隔离级别
    oracle 中SQL 语句开发语法 SELECT INTO含义
  • 原文地址:https://www.cnblogs.com/nowandforever/p/4586909.html
Copyright © 2020-2023  润新知