题意:Wavio序列定义为:长度L=2*n+1 前n+1个严格递增,后n+1个严格递减,给出n个数求满足Wavio的最长子序列
Wavio序列中间点最大,若中间点k,则其长度取决于min(LIS[k],LDS[k]),n<=1e4,O(nlogn)求出以k结尾和开头的LIS,LDS 枚举中间点k即可
L[x]:LIS长度为X的最小a[j] 若L递增 则找到最后一个x,L[x]<a[i] 则a[i]结尾LIS长度为X+1,更新L[x+1]即可
初始时L递增,每次将L[x+1]更新为a[i]时,L[x+1]=a[i]>L[x] 每次更新后依然递增,归纳可得L[0]<L[1]....<L[n]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=1e9;
const int N=2e5+20;
int n,a[N],f[N],g[N];
int L[N];
int main()
{
while(cin>>n)
{
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
L[i]=inf;
L[0]=-inf;
for(int i=1;i<=n;i++)
{
int l=0,r=n;
while(l<=r)
{
int mid=(l+r)>>1;
if(L[mid]<a[i])
l=mid+1;
else
r=mid-1;
}
f[i]=l;
L[l]=a[i];//L[l]>a[i]更新
}
for(int i=1;i<=n;i++)
L[i]=inf;
L[0]=-inf;
for(int i=n;i>=1;i--)
{
int l=0,r=n;
while(l<=r)
{
int mid=(l+r)>>1;
if(L[mid]<a[i])
l=mid+1;
else
r=mid-1;
}
g[i]=l;
L[l]=a[i];//更新
}
int ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,min(f[i],g[i]));
cout<<ans*2-1<<endl;
}
return 0;
}