UVA 10534 - Wavio Sequence - (DP,最长单调上升子序列O(nlogn))

题目链接:

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;
}

猜你喜欢

转载自blog.csdn.net/sdau20163942/article/details/80274803