开始的时候一直想不到一个合适的状态转移方程;
后面想到可以分别求以中间那个数为终点和起点的最长上升子序列的长度,
然后以这个数为中心数的Wavio Sequence的长度就是其中短的那个值*2-1的值;
然后我们取所有数Wavio Sequence的最大长度作为答案。
这个题目卡了n^2的求最长上升子序列的算法,必须用nlgn算法才能过。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[10010],n;
int d1[10010],d2[10010];
int d[10010];
int lower_bound(int* A,int x,int y,int v)
{
int m;
while(x<y)
{
m=x+(y-x)/2;
if(A[m]>=v)
y=m;
else
x=m+1;
}
return x;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
d1[i]=1,d2[i]=1;
int len=1;
d[1]=a[1];
for(int i=2;i<=n;i++)
{
if(a[i]>d[len])
{
d[++len]=a[i];
d1[i]=len;
}
else
{
int t=lower_bound(d,1,len,a[i]);
d[t]=a[i];
d1[i]=t;
}
}
len=1;
d[1]=a[n];
for(int i=n-1;i>=1;i--)
{
if(a[i]>d[len])
{
len++;
d[len]=a[i];
d2[i]=len;
}
else
{
int t=lower_bound(d,1,len,a[i]);
d[t]=a[i];
d2[i]=t;
}
}
int ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,min(d1[i],d2[i])*2-1);
printf("%d\n",ans);
}
return 0;
}