图片加载可能有点慢,请跳过题面先看题解,谢谢
设 \(L[i]\) 为 \(i\) 位置的最长上升子序列的长度
设 \(R[i]\) 为 \(i\) 位置的最长下降子序列的长度
答案为:\(max(min(L[i],R[i])*2-1)\)
这里用到二分栈求 \(LIS\)
//made by Hero_of_Someone
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define il inline
#define RG register
using namespace std;
il int gi(){ RG int x=0,q=1; RG char ch=getchar(); while( ( ch<'0' || ch>'9' ) && ch!='-' ) ch=getchar();
if( ch=='-' ) q=-1,ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; }
int n,cnt,a[10010];
int s[10010],L[10010],R[10010];
il void init(){
for(int i=1;i<=n;i++) a[i]=gi();
}
il void work(){
memset(s,0,sizeof(s)); cnt=0;
for(RG int i=1;i<=n;i++){
RG int x=a[i];
RG int l=1,r=cnt,k=0;
while(l<=r){
RG int mid=(l+r)>>1;
if(s[mid]>=x) r=mid-1;
else l=mid+1,k=mid;
}
if(k==cnt) s[++cnt]=x,L[i]=cnt;
else s[k]=min(s[++k],x),L[i]=L[i-1];
}
memset(s,0,sizeof(s)); cnt=0;
for(RG int i=n;i;i--){
RG int x=a[i];
RG int l=1,r=cnt,k=0;
while(l<=r){
RG int mid=(l+r)>>1;
if(s[mid]>=x) r=mid-1;
else l=mid+1,k=mid;
}
if(k==cnt) s[++cnt]=x,R[i]=cnt;
else s[k]=min(s[++k],x),R[i]=R[i+1];
}
int ans=0;
for(int i=1;i<=n;i++) ans=max(ans,min(L[i],R[i])*2-1);
printf("%d\n",ans);
}
int main(){ while(scanf("%d",&n)!=EOF){ init(); work(); } return 0; }