首先(看题解)可得。。。分成的任意一段中的不同颜色个数都<=根号n。。。不然的话直接分成n段会更优= =

  然后就好做多了。。

  先预处理出对于每头牛i,和它颜色相同的前一头和后一头牛的位置。

  假设当前枚举到第i头牛,pos[j]表示 第pos[j]头~第i头牛之间颜色种数<=j。num[j]表示第pos[j]头~第i头牛之间具体的颜色种数。

  每次i增大时,就要把pos数组和num数组更新。对于新加进来的牛i,如果和它颜色相同的前一头牛不在pos[j]~i的范围中,那么就要把num[j]+1。

  但根据定义,num[j]<=j,所以如果num[j]>j的话就要把pos[j]往i的方向挪。。。如果与第pos[j]头牛颜色相同的后一头牛不在pos[j]~i的范围中,删去第pos[j]头牛后区间里的颜色数量就会-1。。。。

  DP,设f[i]表示将1~i头牛分成若干段的最小不和谐度。。f[i]=min{f[pos[j]-1]+num[j]^2},(1<=j<=n^0.5)。。。

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define us unsigned short
using namespace std;
const int maxn=;
us pre[maxn],next[maxn],precol[maxn],nextcol[maxn];
us a[maxn],b[],c[],f[maxn];//b[j]: b[j]~i中不同数字个数<=j c[j]表示b[j]+1到i出现的不同数字的个数
us i,j,n,m;
us ra;char rx;
inline us read(){
rx=getchar();ra=;
while(rx<''||rx>'')rx=getchar();
while(rx>=''&&rx<='')ra*=,ra+=rx-,rx=getchar();return ra;
}
int main(){
n=read();m=read();
for(i=;i<=m;i++)nextcol[i]=n+;m=floor(sqrt(n));
for(i=;i<=n;i++)
a[i]=read(),pre[i]=precol[a[i]],precol[a[i]]=i;
for(i=n;i;i--)
next[i]=nextcol[a[i]],nextcol[a[i]]=i;
for(i=;i<=m;i++)b[i]=;
for(i=;i<=n;i++)
for(j=;j<=m;j++){
if(pre[i]<b[j]){
c[j]++;
if(c[j]>j){while(next[b[j]]<=i)b[j]++;b[j]++;c[j]--;}
}
if(f[b[j]-]+c[j]*c[j]<f[i]||!f[i])f[i]=f[b[j]-]+c[j]*c[j];
}
printf("%d\n",f[n]);
return ;
}

[bzoj1587] [Usaco2009 Mar]Cleaning Up 打扫卫生的更多相关文章

  1. DP经典 BZOJ 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生

    BZOJ 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 419  Solve ...

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

    BZOJ_1584_[Usaco2009 Mar]Cleaning Up 打扫卫生_DP Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= ...

  3. BZOJ1584 [Usaco2009 Mar]Cleaning Up 打扫卫生

    令$f[i]$表示以i为结尾的答案最小值,则$f[i] = min \{f[j] + cnt[j + 1][i]^2\}_{1 \leq j < i}$,其中$cnt[j + 1][i]$表示$ ...

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

    Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的 ...

  5. 【BZOJ】1584: [Usaco2009 Mar]Cleaning Up 打扫卫生

    [算法]DP+数学优化 [题意]把n个1~m的数字分成k段,每段的价值为段内不同数字个数的平方,求最小总价值.n,m,ai<=40000 [题解] 参考自:WerKeyTom_FTD 令f[i] ...

  6. 【动态规划】bzoj1584: [Usaco2009 Mar]Cleaning Up 打扫卫生

    思路自然的巧妙dp Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分 ...

  7. [BZOJ1584] [Usaco2009 Mar]Cleaning Up 打扫卫生(DP)

    传送门 不会啊,看了好久的题解才看懂 TT 因为可以直接分成n段,所以就得到一个答案n,求解最小的答案,肯定是 <= n 的, 所以每一段中的不同数的个数都必须 <= sqrt(n),不然 ...

  8. bzoj1584 [Usaco2009 Mar]Cleaning Up 打扫卫生 动态规划+思维

    Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的 ...

  9. bzoj 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生【dp】

    参考:http://hzwer.com/3917.html 好神啊 注意到如果分成n段,那么答案为n,所以每一段最大值为\( \sqrt{n} \) 先把相邻并且值相等的弃掉 设f[i]为到i的最小答 ...

随机推荐

  1. Node.js前言

    最近在学Node.js,所以学到一点东西就更新在上面吧,如果有错误,欢迎大家指正.

  2. iOS 轻松实现自定义TabBar

    自定义TabBar的案例网上不少,昨天受到开发小伙伴的影响,尝试了一下非大神的取巧思路:Demo 1.创建RootViewController,后面创建几个继承的VC,将这几个VC添加到TabBarC ...

  3. c#创建access数据库和数据表

      由于在程序中使用了ADOX,所以先要在解决方案中引用之,方法如下: 解决方案资源管理器(项目名称)-->(右键)添加引用-->COM--> Microsoft ADO Ext. ...

  4. Python 多线程进程高级指南(二)

    本文是如何<优雅地实现Python通用多线程/进程并行模块>的后续.因为我发现,自认为懂了一点多线程开发的皮毛,写了那么个multi_helper的玩意儿,后来才发现我靠原来就是一坨屎.自 ...

  5. javascript01

    手敲代码01 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <ti ...

  6. 安卓电量优化之AlarmManager使用全部解析

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.AlarmManager概述 AlarmManager是安卓系统中一种系统级别的提示服务,可以在我们设定时间或者周期性的执行一个intent,这 ...

  7. TP框架如何开启log日志

    1. 日志的处理工作是由系统自动进行的,在开启日志记录的情况下,会记录下允许的日志级别的所有日志信息. 其中,为了性能考虑,SQL日志级别必须在调试模式开启下有效,否则就不会记录. 系统的日志记录由核 ...

  8. Sublime Text3注册码,亲测可用

    将以下复制在输入框即可 ,亲测可用 . 不过还是希望大家多多支持正版 . -– BEGIN LICENSE -– TwitterInc 200 User License EA7E-890007 1D7 ...

  9. ts中interface与class的区别

    interface -- 接口只声明成员方法,不做实现. class -- 类声明并实现方法. 那么接口有什么用呢?设想如下需求: 要实现一个print函数,它将传入的对象打印出来.在实际实现上,它将 ...

  10. form注册表单圆角 demo

    form注册表单圆角 <BODY> <div class="form"> <ul class="list"> <li& ...