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\n",f[n]);
}

最新文章

  1. maxscale
  2. 如何安装sublime text2以及它的插件?
  3. Hive(一):架构及知识体系
  4. Selenium webdriver 之select 控件封装,解决onchange问题
  5. oracle 创建表空间、创建用户管理该表空间
  6. em与px的区别 [ 转 ]
  7. JS 逗号表达式
  8. C#listbox使用方法
  9. scroll运用、图片悬浮
  10. 05-OC多态
  11. Alyona and a tree
  12. :nth-child(n)
  13. Android Java层,Native层,Lib层打印Log简介【转】
  14. vux, vue如何控制微信自带的返回按钮,让其返回其他页面?
  15. 基于Xilinx Zynq Z7045 SoC的CNN的视觉识别应用
  16. 用NI的数据采集卡实现简单电子测试之3——绘制二极管V-I特性曲线图
  17. 使用Supervisor管理Linux进程
  18. iOS直播-基于RTMP的视频推送
  19. 自定义Django的admin界面
  20. axios 讲解 和vue搭建使用

热门文章

  1. nginx配置错误页面
  2. Zabbix微信告警
  3. python爬虫(三)
  4. STM32串口程序的一般配置方法
  5. 洛谷 3871 [TJOI2010]中位数
  6. HDU1024 多段最大和 DP
  7. android framework navigationbar自定义
  8. HDU 5642 King&#39;s Order【数位dp】
  9. java反射-使用反射来操纵方法
  10. 断路器监控(Hystrix Dashboard)