zoukankan      html  css  js  c++  java
  • bzoj1584

    1584: [Usaco2009 Mar]Cleaning Up 打扫卫生

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 467  Solved: 316
    [Submit][Status][Discuss]

    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

    HINT

    Source

    Gold

    不愿意动脑子,也想不出来

    首先我们可以发现,因为最小值最大也就是n,也就是把所有东西分成长度为1的段

    所以我们可以知道绝对不可以让一段有>=n^0.5种数字

    考虑dp,设b[j]为一段有j种数字,最近对应的位置(区间为i-b[j]+1),pre[i]:上一个数字i出现的位置,cnt[j]:其实记录更新时有没有修改。

    方程就得出了:f[i]=min{f[b[j]]+j*j} 1<=j<=n^0.5 复杂度为O(n^1.5)

    怎么更新b呢?可以发现,当一个新的数字被加进时,b[j]有可能修改,当且仅当从i-b[j]+1中没有这个数字,这时我们用cnt记录被修改,然后一个一个向前找,直到我们可以删掉一个数字,使得这段中有j个数字

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define N 40010
    int n,m;
    int f[N],a[N],pre[N],b[N],cnt[N];
    int main()
    {
        memset(f,0x3f,sizeof(f)); f[0]=0;
        memset(pre,-1,sizeof(pre)); 
        scanf("%d%d",&n,&m); 
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        int size=(int)(sqrt(n)); 
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=size;j++) {
                if(pre[a[i]]<=b[j]) cnt[j]++;
            }
            pre[a[i]]=i;
            for(int j=1;j<=size;j++) {
                if(cnt[j]>j) {
                    int pos=b[j]+1;
                    while(pre[a[pos]]>pos) pos++; 
                    b[j]=pos; cnt[j]--;
                }
            }
            for(int j=1;j<=size;j++) {
                f[i]=min(f[i],f[b[j]]+j*j);
            }
        }
        printf("%d",f[n]);
        return 0;
    }
    View Code
  • 相关阅读:
    poj 3068 Bridge Across Islands
    XidianOJ 1086 Flappy v8
    XidianOJ 1036 分配宝藏
    XidianOJ 1090 爬树的V8
    XidianOJ 1088 AK后的V8
    XidianOJ 1062 Black King Bar
    XidianOJ 1091 看Dota视频的V8
    XidianOJ 1098 突击数论前的xry111
    XidianOJ 1019 自然数的秘密
    XidianOJ 1109 Too Naive
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6185244.html
Copyright © 2011-2022 走看看