• 洛谷P2943 清理——DP


    题目:https://www.luogu.org/problemnew/show/P2943

    一眼看去就有个 n^2 的做法:f[i] = min{ f[j] + num( i - j ) * num( i - j ) } , 1 <= j < i;

    但仔细想想这个做法,发现那个num数组很不好处理;

    也就是我们需要关注一个区间内食品的种类数;

    不妨根据这个来调整做法,直接枚举种类数;

    这样做的好处是可以进行转移,因为从 i 到 i+1 会带来一个种类数量的改变;

    由此受到启发,设数组 pos[j] 为种类数是 j 时可到达的最远节点(越远越优);

    再对每个点记录一下前驱后继以便于进行种类数是否增加的判断;

    cnt数组记录 pos[j] 到 i 这一段(实际的)种类数,就可以转移了。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const maxn=40005;
    int n,m,f[maxn],pos[maxn],cnt[maxn],pre[maxn],nxt[maxn],lst[maxn],a[maxn];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1,x;i<=n;i++)
        {
            scanf("%d",&x);a[i]=x;
            pre[i]=lst[x];
            nxt[lst[x]]=i;
            lst[x]=i;
            nxt[i]=n+1;
        }
        for(int i=1;i*i<=n;i++)pos[i]=1;//!
        memset(f,0x3f,sizeof f);
        f[0]=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j*j<=n;j++)
            {
                if(pre[i]<pos[j])cnt[j]++;
                if(cnt[j]>j)
                {
                    cnt[j]--;
                    while(nxt[pos[j]]<=i)pos[j]++;
                    pos[j]++;
                }
                f[i]=min(f[i],f[pos[j]-1]+j*j);
            }
        printf("%d",f[n]);
        return 0;
    }
  • 相关阅读:
    JQuery UI
    JQuery 插件
    JQuery Ajax
    varchar和Nvarchar区别
    git冲突解决
    jquery ajax 提交信息后等待返回的提示信息
    Oracle错误 ORA-12560如何解决
    putty ssh连接老断
    myeclipse操作记录
    HTML与HTML5笔记
  • 原文地址:https://www.cnblogs.com/Zinn/p/9164456.html
Copyright © 2020-2023  润新知