• POJ 1952 BUY LOW, BUY LOWER


    $dp$。

    一开始想了一个$dp$做法,$dp[i][j]$表示前$i$个数字,下降序列长度为$j$的方案数为$dp[i][j]$,这样做需要先离散化然后用树状数组优化,空间复杂度为${n^2}$,时间复杂度为$O({n^2}log n)$,这样的做法被$POJ$卡了内存。既然是$MLE$,然后我去$discuss$测了一下数据,发现答案都是对的。

    $MLE$:

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-8;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    
    const int maxn=5010;
    int f[maxn][maxn],h[maxn][maxn],n,a[maxn],b[maxn];
    int c[maxn][maxn];
    int pre[(1<<16)+20];
    
    int get(int x)
    {
        int L=1,R=n,res;
        while(L<=R)
        {
            int mid=(L+R)/2;
            if(b[mid]<x) L=mid+1;
            else if(b[mid]==x) res=mid,L=mid+1;
            else R=mid-1;
        }
        return res;
    }
    
    int lowbit(int x){return x&(-x);}
    
    int sum(int p,int x)
    {
        int res=0;
        for(int i=x;i>0;i=i-lowbit(i)) res=res+c[p][i];
        return res;
    }
    
    void update(int p,int x,int val)
    {
        for(int i=x;i<=5001;i=i+lowbit(i)) c[p][i]=c[p][i]+val;
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
        sort(b+1,b+1+n); for(int i=1;i<=n;i++) a[i]=get(a[i]);
    
        memset(h,0,sizeof h); memset(c,0,sizeof c);
        memset(f,0,sizeof f);
        memset(pre,0,sizeof pre);
    
        h[0][0]=1; f[0][0]=1; update(0,5001,1);
    
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=i;j++) h[i][j]=sum(j-1,5001)-sum(j-1,a[i]);
            int p=pre[a[i]];
            for(int j=1;j<=n;j++) f[i][j]=h[i][j]-h[p][j];
            for(int j=1;j<=n;j++) update(j,a[i],f[i][j]);
            pre[a[i]]=i;
        }
        for(int j=n;j>=1;j--)
        {
            int ans=0;
            for(int i=1;i<=n;i++) ans=ans+f[i][j];
            if(ans==0) continue;
            else
            {
                printf("%d %d
    ",j,ans);
                break;
            }
        }
    
        return 0;
    }
    View Code

     事实上,上述做法中很多信息都是冗余的,我们只需记录到$i$位置的最长下降序列的长度$f[i]$以及方案数$g[i]$就可以了。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-8;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    
    const int maxn=5010;
    int n,a[maxn],f[maxn],g[maxn];
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    
        for(int i=1;i<=n;i++)
        {
            f[i]=1; g[i]=1; bool flag=0;
            for(int j=i-1;j>=1;j--)
            {
                if(a[j]<a[i]) continue;
                if(a[j]==a[i])
                {
                    if(flag==0) g[i]=0;
                    break;
                }
                else if(a[j]>a[i])
                {
                    flag=1;
                    if(f[j]+1>f[i]) f[i]=f[j]+1,g[i]=g[j];
                    else if(f[j]+1==f[i]) g[i]=g[i]+g[j];
                }
            }
        }
    
        int ans=0; for(int i=1;i<=n;i++) ans=max(ans,f[i]);
        int ans2=0; for(int i=1;i<=n;i++) if(f[i]==ans) ans2=ans2+g[i];
        printf("%d %d
    ",ans,ans2);
    
        return 0;
    }
  • 相关阅读:
    甲午年总结
    浅谈数字营销
    机器学习笔记
    上海GDG活动有感
    我也谈谈游戏
    CSS3新增属性
    js事件详解
    DOM与BOM相关操作
    JS基础知识
    js数据类型
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5824488.html
Copyright © 2020-2023  润新知