hdu 4604 动态规划

思路:这题的感觉就是最长上升子序列的升级版。首先对于最长上升子序列要用n*log(n)的算法才行,这个复杂度的算法可以从hdu1025得到启发。然后就是什么情况下最优问题了。对于序列中某个数i,找出其后面最长不下降子序列长度和最长不上升子序列长度,将这两个长度加起来,最大的就是我们要找到。但由于存在相同值,那么我么就要确定这两个子序列中值为i的个数最少的那个,用上面求得和减去它。

我的代码比较挫。

#include<iostream>

#include<cstring>

#include<cmath>

#include<string>

#include<cstdio>

using namespace std;

int ans[200010],list[100010],low[100010],more[100010],same[100010];

int main()

{

    int t,n,i,j;

    scanf("%d",&t);

    while(t--)

    {

        scanf("%d",&n);

        memset(low,0,sizeof(low));

        memset(more,0,sizeof(more));

        memset(same,0,sizeof(same));

        for(i=1;i<=n;i++)

            scanf("%d",&list[i]);

        int len;

        ans[1]=list[n];

        low[n]=1;

        len=1;

        same[n]=1;

        int l,r,mid;

        for(i=n-1;i>=1;i--)

        {

            if(ans[len]>=list[i])

            {

                ans[++len]=list[i];

                low[i]=len;

            }

            else

            {

            l=1;

            r=len;

            while(l<=r)

            {

                 mid=(l+r)>>1;

                if(ans[mid]>=list[i])

                    l=mid+1;

                else

                    r=mid-1;

            }

            ans[l]=list[i];

            low[i]=l;

            }

            l=1,r=len;

            while(l<=r)

            {

                mid=(l+r)>>1;

                if(ans[mid]>list[i])

                    l=mid+1;

                else

                    r=mid-1;

            }

            same[i]=low[i]-r;

        }

        ans[1]=list[n];

        len=1;

        more[n]=1;

        for(i=n-1;i>=1;i--)

        {

            if(ans[len]<=list[i])

            {

                ans[++len]=list[i];

                more[i]=len;

            }

            else

            {

            l=1;

            r=len;

            while(l<=r)

            {

                 mid=(l+r)>>1;

                if(ans[mid]<=list[i])

                    l=mid+1;

                else

                    r=mid-1;

            }

            ans[l]=list[i];

            more[i]=l;

            }

            l=1,r=len;

            while(l<=r)

            {

                mid=(l+r)>>1;

                if(ans[mid]<list[i])

                    l=mid+1;

                else

                    r=mid-1;

            }

            same[i]=min(more[i]-r,same[i]);

        }

        int Ans=0;

        for(i=1;i<=n;i++)

            Ans=max(Ans,low[i]+more[i]-same[i]);

        printf("%d\n",Ans);

    }

    return 0;

}

 

你可能感兴趣的:(动态规划)