一道思维题,代码很简单,重在思路
设
l
i
l_i
li 为以元素
i
i
i 结尾的最长连续上升子序列的长度
r
i
r_i
ri 为以元素
i
i
i 开头的最长连续上升子序列的长度
最后, a n s ans ans 由三个东西转移过来: a n s = m a x { max i = 2 n − 1 l i − 1 + 1 + r i + 1 , max i = 2 n − 1 l i − 1 + 1 , max i = 2 n − 1 r i + 1 + 1 } ans = max\{ \max\limits_{i=2}^{n-1} l_{i-1}+1+r_{i+1},\max\limits_{i=2}^{n-1} l_{i-1}+1,\max\limits_{i=2}^{n-1} r_{i+1}+1 \} ans=max{i=2maxn−1li−1+1+ri+1,i=2maxn−1li−1+1,i=2maxn−1ri+1+1}
- 将 i i i 左右两边的连续上升序列拼起来,然后修改元素 i i i,构成一个更长的上升序列
- 修改元素 i i i,使得它可以加到前面的上升序列的尾部
- 修改元素
i
i
i,使得它可以加到后面的上升序列的头部
这里方法2 和 方法3 对应的是元素 i i i 两边不存在上升序列的情况
#include<cstdio>
#include<iostream>
using namespace std;
const int Maxn=100000+10;
int a[Maxn],l[Maxn],r[Maxn];
int n,ans;
int main()
{
// freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",a+i);
l[1]=r[n]=1;
for(int i=2;i<=n;++i) // 计算 l[i],r[i]
if(a[i-1]<a[i])l[i]=l[i-1]+1;
else l[i]=1;
for(int i=n-1;i;--i)
if(a[i]<a[i+1])r[i]=r[i+1]+1;
else r[i]=1;
for(int i=1;i<=n;++i) // 这里的边界写的跟上面描述的不一样,其实没区别
{
ans=max(ans,l[i-1]+1);
ans=max(ans,1+r[i+1]);
if(a[i-1]+1<a[i+1])
ans=max(ans,l[i-1]+1+r[i+1]); // 求出答案
}
printf("%d\n",ans);
return 0;
}