码迷,mamicode.com
首页 > 其他好文 > 详细

最长上升子序列模型

时间:2020-02-18 23:23:19      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:过程   链接   str   nlog   int   line   ++   return   mes   

题目链接\(O(N^2)\)能过。
题目链接\(O(N\log N)\)能过。

\(O(N^2)\)做法

DP:f[i]表示,以第i个数结尾的最长子序列的集合的最大值。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;

int n;
int a[N], f[N];

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];

    for (int i = 1; i <= n; i++)
    {
        f[i] = 1; // 初始化,最小也有它一个数,所以初始化成1
        for (int j = 1; j < i; j++)
            if (a[j] < a[i])
                f[i] = max(f[i], f[j] + 1);
    }
    
    int ans = 0;
    for (int i = 1; i <= n; i++) ans = max(ans, f[i]);

    cout << ans << endl;

    return 0;
}

\(O(N\log N)\)做法

再开一个数组,记录长度为x的子序列中最后一个数最小的数。

例如 1 3 8 与 1 2 3 均为长度为三的序列,则新开的数组q[3] = 3

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 100010;

int n;
int a[N], q[N];

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);

    int len = 0; // 用来记录找的过程中子序列的最大值
    //int q[0] = -2e9;
    for (int i = 1; i <= n; i++)
    {
        // 二分寻找q数组中小于a[i]的最大值
        // 二分的套路:确定边界, 求mid, 设计check函数
        int l = 0, r = len;
        while (l < r)
        {
            int mid = l + r + 1 >> 1;
            if (q[mid] < a[i]) l = mid;
            else r = mid - 1;
        }
        len = max(len, r + 1); // 更新长度
        q[r + 1] = a[i]; // 把a[i]放进去
    }

    cout << len << endl;

    return 0;
}

最长上升子序列模型

标签:过程   链接   str   nlog   int   line   ++   return   mes   

原文地址:https://www.cnblogs.com/optimjie/p/12329302.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!