小明现在有一个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; }