zoukankan      html  css  js  c++  java
  • BZOJ_1584_[Usaco2009 Mar]Cleaning Up 打扫卫生_DP

    BZOJ_1584_[Usaco2009 Mar]Cleaning Up 打扫卫生_DP

    Description

    有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000。现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k。那总的不河蟹度就是所有段的不河蟹度的总和。

    Input

    第一行:两个整数N,M

    第2..N+1行:N个整数代表每个奶牛的编号

    Output

    一个整数,代表最小不河蟹度

    Sample Input

    13 4
    1
    2
    1
    3
    2
    2
    3
    4
    3
    4
    3
    1
    4

    Sample Output

    11


    设F[i]表示前i个数分成若干段。

    首先能看出来不同的数最多只需要根号n个,再多就不如一个一个取了。

    如果我们能求出来L[j]表示当前选j个不同的数最早能到哪,那么有F[i]=min(F[i],F[L[j]-1]+j*j)。

    其中L[j]是和F[i]一起转移的。

    那么我们维护根号n个指针求L即可。

    代码:

    #include <cstdio>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    using namespace std;
    #define N 40050
    int n,m,a[N],L[250],H[250][40050],cnt[250],f[N];
    int main() {
        scanf("%d%*d",&n); int i,j;
        for(m=sqrt(n),i=1;i<=n;i++) scanf("%d",&i[a]);
        for(i=1;i<=m;i++) L[i]=1;
        memset(f,0x3f,sizeof(f)); f[0]=0;
        for(i=1;i<=n;i++) {
            for(j=1;j<=m;j++) {
                H[j][a[i]]++; if(H[j][a[i]]==1) cnt[j]++;
                while(cnt[j]>j&&L[j]<=i) {
                    H[j][a[L[j]]]--; if(H[j][a[L[j]]]==0) cnt[j]--; L[j]++;
                }
                f[i]=min(f[i],f[L[j]-1]+j*j);
            }
        }
        printf("%d
    ",f[n]);
    }
    
    
  • 相关阅读:
    Python 开发中easy_install的安装及使用
    Python 对象的深拷贝与浅拷贝 -- (转)
    Python 语言使用中遇到的问题汇总
    Python 源码学习之内存管理 -- (转)
    Python 对象模型 -- (转)
    Python3.3.3 安装(Linux系统)
    angular-file-upload API angular文件上传插件
    html5上传文件并监听进度
    angular 服务
    skrollr 中文教程
  • 原文地址:https://www.cnblogs.com/suika/p/9126926.html
Copyright © 2011-2022 走看看