DP - 最長上升子序列(nlogn模板) - Wavio Sequence - UVA - 10534

DP - 最長上升子序列(nlogn模板) - Wavio Sequence - UVA - 10534

題意:

n多組測試數據,每組包括一個長度爲n的序列。

求這個序列中最長的“凸”序列的長度。

“凸”序列:先嚴格遞增,再嚴格遞減,且遞增的長度與遞減的長度相同。

舉例:

1 2 3 2 1 2 3 4 3 2 1 5 4 1 2 3 2 2 1
the longest Wavio sequence is : 1 2 3 4 5 4 3 2 1

5552×51=9元素5的左側嚴格遞增的長度爲5,右側嚴格遞減的長度爲5,總長度爲2×5-1=9。

Sample Input:
10
1 2 3 4 5 4 3 2 1 10
19
1 2 3 2 1 2 3 4 3 2 1 5 4 1 2 3 2 2 1
5
1 2 3 4 5

Sample Output:
9
9
1

數據範圍:

1<=n<=10000Time limit3000 ms1<=n<=10000\\Time\ limit:3000 \ ms


分析:

與——《DP - 最長上升子序列模型 - NOIP2004提高組 - 合唱隊形 + 北京大學ACM/ICPC選拔賽 - 登山》類似。

調區別在於:本題要求中心兩側單調的序列長度相同。

iires2×res1那麼與上述模型類似的,正反兩遍做最長上升子序列後,\\對中心i,要取i左側嚴格遞增序列長度與右側嚴格遞減序列長度的較小值res。\\最終結果應當是2×res-1。

需要注意的是:

10000O(n2)調+本題數據範圍是10000,因此O(n^2)的樸素寫法被卡掉了,要用單調隊列+二分優化。

代碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>

#define ll long long
#define inf 0x3f3f3f3f

using namespace std;

const int N=10010;

int n,a[N],f1[N],f2[N];

int main()
{
    while(~scanf("%d",&n))
    {
        memset(f1,0,sizeof f1);
        memset(f2,0,sizeof f2);

        for(int i=1;i<=n;i++) scanf("%d",&a[i]);

        int q[N];
        q[0]=-1e9;int len=0;
        for(int i=1;i<=n;i++)
        {
            int l=0,r=len;
            while(l<r)
            {
                int mid=l+r+1>>1;
                if(q[mid]<a[i]) 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);
        q[0]=-1e9;len=0;
        for(int i=n;i;i--)
        {
            int l=0,r=len;
            while(l<r)
            {
                int mid=l+r+1>>1;
                if(q[mid]<a[i]) l=mid;
                else r=mid-1;
            }
            len=max(len,r+1);
            f2[i]=r+1;
            q[r+1]=a[i];
        }

        int res=1;
        for(int i=1;i<=n;i++) res=max(res,min(f1[i],f2[i]));

        printf("%d\n",2*res-1);
    }

    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章