题目链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1475
题意:Wavio sequence是指一个长度为奇数的串,以正中间的点为最高点往两端单调下降的序列,给出长为n的串,求它的最长Wavio sequence子串。
解析:对于每个点i求出从左段到i的最长单调上升子序列长度lr[i],再求出从i到右段的最长单调下降子序列长度rl[i],对于每个点的ans[i]为min(lr[i],rl[i])的2倍,即以i为最高点的Wavio sequence子序列。这里要用时间复杂度为O(nlogn)的算法来求最长单调上升子序列。
代码:
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll M = 10005;
int ans,n,cnt;
int s[M],dp[M];
int lr[M],rl[M];
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(dp,0,sizeof(dp));
ans=1;cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&s[i]);
int k=lower_bound(dp,dp+cnt,s[i])-dp;
dp[k]=s[i];
if(k==cnt) cnt++;
lr[i]=cnt;//lr[i]是数组a中,从左到右最长上升子序列的长度
}
cnt=0;
memset(dp,0,sizeof(dp));
for(int i=n;i>=1;i--)
{
int k=lower_bound(dp,dp+cnt,s[i])-dp;
dp[k]=s[i];
if(k==cnt) cnt++;
rl[i]=cnt;//rl[i]是数组a中,从右到左最长上升子序列的长度
ans=max(ans,(min(rl[i],lr[i])*2));
}
printf("%d\n",ans-1);
}
return 0;
}