小明的数列

题目描述

小明现在有一个n个数组成的数列,小明现在想取一个连续的子序列,并且这个子序列还必须得满足:最多只改变一个数,就可以使得这个连续的子序列是一个严格上升的子序列,小明想知道这个连续子序列最长的长度是多少。

 

输入

输入包括两行,第一行包括一个整数n(1 ≤ n ≤ 10^5),即数列的长度;
第二行n个整数a_i, 表示数列中的每个数(1 ≤ a_i ≤ 10^9),以空格分割。

 

输出

输出一个整数,表示最长的长度。

 

样例输入
6 
7 2 3 1 5 6
样例输出
5

最长上升子序列的变形,要从前往后求一遍,从后往前求一遍,枚举中间点。。。

主要思想是从前往后扫一遍和从后往前扫一遍。。。

参考博客 http://blog.csdn.net/u010770184/article/details/72599980

#include <stdio.h>
#include <math.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <queue>
#define maxn 100005
using namespace std;
int a[maxn];
struct node
{
    int l,r,sum;
};
node num[maxn];
bool cmp(node a,node b)
{
    return a.l < b.l;
}
int main()
{
    int n;
    while(cin >> n)
    {
        for(int i=0;i<n;i++)
            cin >> a[i];
        int ll = 0,j = 0,ans = 1;
        for(int i=1;i<n;i++)//从前往后扫一遍
        {
            if(i==n-1||a[i]<=a[i-1])
            {
                num[j].l = ll;
                if(i==n-1)
                    num[j].r = i;
                else num[j].r = i-1; 
                num[j].sum = num[j].r - num[j].l + 1;
                ans = max(ans,num[j].sum);
                j++;
                ll = i;
            }
        }
        sort(num,num+j,cmp);
        for(int i=0;i<j-1;i++)
        {
            int p = num[i].r;
            int q = num[i+1].l;
            if(num[i+1].sum==1)
                ans = max(ans,num[i].sum+1);
            else if(num[i].sum==1)
                ans = max(ans,num[i+1].sum+1);
            else 
            {
                if(a[p]+1<a[q+1])
                    ans = max(ans,num[i].sum+num[i+1].sum);
                if(a[p-1]+1<a[q])
                    ans = max(ans,num[i].sum+num[i+1].sum);
            }
        }
        cout << ans << endl;
    }
    return 0; 
}

 

posted on 2017-05-21 21:54  九月旧约  阅读(288)  评论(0编辑  收藏  举报

导航