[编程题] 牛牛的数列
时间限制:1秒
空间限制:32768K
牛牛现在有一个n个数组成的数列,牛牛现在想取一个连续的子序列,并且这个子序列还必须得满足:最多只改变一个数,就可以使得这个连续的子序列是一个严格上升的子序列,牛牛想知道这个连续子序列最长的长度是多少。
输入描述:
输入包括两行,第一行包括一个整数n(1 ≤ n ≤ 10^5),即数列的长度; 第二行n个整数a_i, 表示数列中的每个数(1 ≤ a_i ≤ 10^9),以空格分割。
输出描述:
输出一个整数,表示最长的长度。
输入例子:
6 7 2 3 1 5 6
输出例子:
5
解题思路:
正着枚举记录一下当前位置的连续上升子序列长度,倒着也做一遍。
最后枚举一个连接点即可。
1)对于每一位置i 正向记录到i递增的长度pre[i] (如果a[i]>a[i-1] 则pre[i] = pre[i-1] + 1否则等于1)
2)对于每一位置i 反向记录到i递减的长度suf[i] (如果a[i]<a[i+1] ]则suf[i] = suf[i+1] + 1否则等于1)
3)针对每一要替换的位置i 比较当前ans pre[i-1] suf [i+1] 中的最大值
对于a[i+1] -a[i-1]>=2 证明a[i]可替换 然后计算ans 和pre[i-1] + suf[i+1] +1中的最大值
注意a[0] a[n+1] 均定义最大值,使得在比较时不会越界且不影响处理结果
1 #include <iostream> 2 3 using namespace std; 4 const int INF = 0x3f3f3f3f;//10^9级别 5 int main() 6 { 7 int n; 8 while(cin>>n) 9 { 10 int a[n+2]; 11 int pre[n+1];//记录从左到右连续递增子序列的长度 12 pre[0] = 0; 13 int suf[n+2];//记录从左到右连续递减子序列的长度 14 suf[n+1] = 0; 15 a[0] = INF; 16 a[n+1] = INF; 17 int ans = 1; 18 for(int i=1;i<=n;i++) 19 { 20 cin>>a[i]; 21 } 22 for(int i=1;i<=n;i++) 23 { 24 if(a[i-1] < a[i]) 25 { 26 pre[i] = pre[i-1] + 1; 27 } 28 else 29 { 30 pre[i] = 1; 31 } 32 } 33 for(int i=n;i>=1;i--) 34 { 35 if(a[i] < a[i+1]) 36 { 37 suf[i] = suf[i+1] + 1; 38 } 39 else 40 { 41 suf[i] = 1; 42 } 43 } 44 //对于每一位置i有左侧到它最长的连续子序列长度pre[i] 右侧有连续递增子序列长度suf[i] 45 //对于分界i ans就为ans和将当前i替换中的最大值,即ans pre[i-1]+1 suf[i+1]+1 这三个值中的最大值 46 //到分界i 求出它左右中的最大值 如果a[i+1]和a[i-1]差2或者以上则i位可以替换 则结果就为suf[i+1] +pre[i-1]+1 47 for(int i = 1; i <= n; i++) 48 { 49 ans = max(ans, pre[i - 1] + 1); 50 ans = max(ans, suf[i + 1] + 1); 51 if(a[i + 1] - a[i - 1] >= 2) 52 ans = max(ans, pre[i - 1] + suf[i + 1] + 1); 53 } 54 cout<<ans<<endl; 55 } 56 return 0; 57 }