题面
Mushroom 手中有 n 个数排成一排,现在 Mushroom 想取一个连续的子序列,使得这个子序列满足:最多只改变一个数,使得这个连续的子序列是严格上升子序列,Mushroom 想知道这个序列的最长长度是多少。
分析
先开始以为是dp,后来发现忽略了连续这个要求,不过样例给的是 7 2 3 1 5 6,很明显是把1改成4,就会有长度为5的严格上升子序列
我发现,1的左右都存在长度较长的上升子序列,于是考虑到预处理以每个位置结束和每个位置开始的连续上升子序列长度,O(N)递推
再枚举修改哪个数字,ans=max{ 以i-1结尾的上升序列长+以i+1开始的上升序列长+1 },前提是a[i+1]-a[i-1]>1
有特殊情况,比如前后拼接不起来,只能用前面一段或者后面一段
序列长为1的时候,显然答案为1,长度>1时,最小答案显然是2
#include<bits/stdc++.h> using namespace std; #define N 100100 int n,ans; int s[N],a[N],fs[N],fj[N]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); fs[n]=1; for(int i=n-1;i>=1;i--) fs[i]=a[i+1]>a[i]?fs[i+1]+1:1; fj[1]=1; for(int i=2;i<=n;i++) fj[i]=a[i-1]<a[i]?fj[i-1]+1:1; ans=min(n,2); for(int i=1;i<=n;i++) if(a[i+1]-a[i-1]>1) ans=max(ans,fs[i+1]+fj[i-1]+1); for(int i=1;i<=n;i++) { ans=max(ans,min(n,fs[i]+1)); ans=max(ans,min(n,fj[i]+1)); } printf("%d",ans); return 0; }