思路
是一个最长上升子序列题,这里要dp两边,一个从前往后,一个从后往前,每个点的值就是左右两边长度的最小值*2-1。当然,这里的dp是要用二分的,朴素版的过不去。
代码
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e5+5;
int a[N];
int f1[N],f2[N];
int q[N];
int main()
{
int n;
while(cin >> n){
int len=0;
for(int i=1;i<=n;i++)cin >> a[i];
for(int i=1;i<=n;i++){
int l=0;int r=len;
while(l<r){
int mid=(l+r+1)>>1;
if(a[i]>q[mid])l=mid;
else r=mid-1;
}
len=max(len,r+1);
f1[i]=r+1;
q[r+1]=a[i];
}
memset(q,0,sizeof q);
len=0;
for(int i=n;i>=1;i--){
int l=0;int r=len;
while(l<r){
int mid=(l+r+1)>>1;
if(a[i]>q[mid])l=mid;
else r=mid-1;
}
len=max(len,r+1);
f2[i]=r+1;
q[r+1]=a[i];
}
int ans=1;
int tmp;
for(int i=1;i<=n;i++){
tmp=min(f1[i],f2[i]);
ans=max(ans,tmp*2-1);
}
cout << ans << "\n";
}
}