zoukankan      html  css  js  c++  java
  • 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
    ",Ans);
        }
        return 0;
    }
  • 相关阅读:
    快速排序和随机化快排学习
    P1330 封锁阳光大学 DFS
    P2577 [ZJOI2005]午餐 状压DP
    M. Subsequence 南昌邀请赛
    P1441 砝码称重 DFS回溯+DP
    P2661 信息传递 二分图的最小环
    P1196 [NOI2002]银河英雄传说 带权并查集
    P2024 [NOI2001]食物链 并查集
    F. Shovels Shop 背包DP
    P1514 引水入城 DFS
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3209536.html
Copyright © 2011-2022 走看看