链接:牛牛的数列
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K 64bit IO
Format: %lld
题目描述
牛牛现在有一个n个数组成的数列,牛牛现在想取一个连续的子序列,并且这个子序列还必须得满足:最多只改变一个数,就可以使得这个连续的子序列是一个严格上升的子序列,牛牛想知道这个连续子序列最长的长度是多少。
输入描述:
输入包括两行,第一行包括一个整数n(1 ≤ n ≤ 10^5),即数列的长度;
第二行n个整数a_i, 表示数列中的每个数(1 ≤ a_i ≤ 10^9),以空格分割。
输出描述:
输出一个整数,表示最长的长度。
示例
输入
6 7 2 3 1 5 6
输出
5
实现代码
#include<iostream>
using namespace std;
const int maxn = 1e5 + 3;
// a用于数组存储,后两个分别存储左连续上升序列,右连续下降序列
int a[maxn], left_increase[maxn], right_decrease[maxn];
int n;
void init(int n){
for(int i = 0; i < n; i++) left_increase[i] = right_decrease[i] = 1;
}
int main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n;
init(n);
for(int i = 0; i < n; i++) cin >> a[i];
// 找左连续上升序列
for(int i = 1; i < n; i++){
if(a[i] > a[i - 1]) left_increase[i] = left_increase[i - 1] + 1;
}
// 找右连续下降序列
for(int i = n - 2; i >= 0; i--){
if(a[i] <a[i + 1]) right_decrease[i] = right_decrease[i + 1] + 1;
}
int ans = left_increase[n - 1];
// 忽略第i个数
for(int i = 1; i < n - 1; i++) {
if(ans == n) break; // 若ans已经最大,就无须再找了
ans = max(ans, left_increase[i]);
ans = max(ans, right_decrease[i]);
// 若两个相邻数之间还有空位
if(a[i + 1] - a[i - 1] >= 2) {
ans = max(ans, left_increase[i - 1] + right_decrease[i + 1] + 1);
}
}
cout << ans << endl;
return 0;
}