码迷,mamicode.com
首页 > Windows程序 > 详细

AcWing 1490. 最长上升子串 模拟优化

时间:2020-06-21 16:00:28      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:最长上升子串   数字   main   namespace   接下来   print   遍历   数据   统计   

地址 https://www.acwing.com/solution/content/15094/

给出一个长度为 n 的由正整数构成的序列,你需要从中删除一个正整数,很显然你有很多种删除方式,你需要对删除这个正整数以后的序列求其最长上升子串,请问在所有删除方案中,最长的上升子串长度是多少。

这里给出最长上升子串的定义:即对于序列中连续的若干个正整数,满足 ai+1>ai,则称这连续的若干个整数构成的子串为上升子串,在所有的上升子串中,长度最长的称为最长上升子串。

输入格式
输入第一行仅包含一个正整数 n,表示给出的序列的长度。

接下来一行有 n 个正整数,即这个序列,中间用空格隔开。

输出格式
输出仅包含一个正整数,即删除一个数字之后的最长上升子串长度。

数据范围
1≤n≤105,
1≤ai≤105
输入样例:
5
2 1 3 2 5
输出样例:
3

算法1
首先考虑使用暴力遍历解答,逐个删除某个数字然后双指针统计上升子串的长度。
过程中我们会发现,如果删除该元素 对于上升子串没有提升的长度 则可以考虑剪枝。
对于上升子串没有提升的长度的定义呢 就是该数字的左边的数小于该数字右边的数。
那么进一步的优化,如果我们首先统计以该数字为结尾和以该数字为开始 的上升子串的长度,
可以减少不少的计算量。

类似如此
a b c d 如果我们实现统计了 以各个元素为结尾的最长上升子串长度 ai bi ci di
统计了 以各个元素为起始的最长上升子串长度 aj bj cj dj.

那么如果 a < c 我们可以尝试删除b,得到子串长度就是 ai+bj;
但如果b < d 我们可以尝试删除c,得到的子串长度就是bi+dj;

代码实现见Y总得示例代码

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

using namespace std;

const int N = 100010;

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

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

    // 预处理f[i]:以i结尾的单调上升子串的最大长度
    for (int i = 1; i <= n; i ++ )
        if (a[i] > a[i - 1]) f[i] = f[i - 1] + 1;
        else f[i] = 1;

    // 预处理g[i]:以i开头的单调上升子串的最大长度
    for (int i = n; i; i -- )
        if (a[i] < a[i + 1]) g[i] = g[i + 1] + 1;
        else g[i] = 1;

    int res = 0;
    // 枚举删除哪个数
    for (int i = 1; i <= n; i ++ )
        if (a[i - 1] >= a[i + 1]) res = max(res, max(f[i - 1], g[i + 1]));
        else res = max(res, f[i - 1] + g[i + 1]);

    printf("%d\n", res);

    return 0;
}

 

AcWing 1490. 最长上升子串 模拟优化

标签:最长上升子串   数字   main   namespace   接下来   print   遍历   数据   统计   

原文地址:https://www.cnblogs.com/itdef/p/13172362.html

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