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

[文章目录]

Description

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

显然答案不超过n,那么显然每段所含有不同的数的个数不超过根号n。Dp,f[i]表示1~i的最小不和谐度,转移只需要通过离i前根号个不同的数的位置即可,set维护。时间复杂度O(n√n)

#include <set>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 41000 
int n,m;
int a[N],dp[N],tid[N];
set<int>s;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) scanf("%d",a+i),dp[i]=i;
    int lim,k; lim=sqrt((double)n)+10;
    set<int>::iterator it;
    for(int i=1;i<=n;++i)
    {
        it=s.find(tid[a[i]]); tid[a[i]]=i;
        if(it!=s.end()) s.erase(it),s.insert(i);
        else
        {
            if((int)s.size()>=lim) s.erase(s.begin());
            s.insert(i);
        }
        k=s.size();
        for(it=s.begin();it!=s.end();it++)
        {
            k--;
            dp[i]=min(dp[i],dp[*it]+k*k);
        }
    }
    printf("%d",dp[n]);
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注