BZOJ_1584_[Usaco2009 Mar]Cleaning Up 打扫卫生_DP
2024-09-04 07:05:40
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
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]);
}
最新文章
- maxscale
- 如何安装sublime text2以及它的插件?
- Hive(一):架构及知识体系
- Selenium webdriver 之select 控件封装,解决onchange问题
- oracle 创建表空间、创建用户管理该表空间
- em与px的区别 [ 转 ]
- JS 逗号表达式
- C#listbox使用方法
- scroll运用、图片悬浮
- 05-OC多态
- Alyona and a tree
- :nth-child(n)
- Android Java层,Native层,Lib层打印Log简介【转】
- vux, vue如何控制微信自带的返回按钮,让其返回其他页面?
- 基于Xilinx Zynq Z7045 SoC的CNN的视觉识别应用
- 用NI的数据采集卡实现简单电子测试之3——绘制二极管V-I特性曲线图
- 使用Supervisor管理Linux进程
- iOS直播-基于RTMP的视频推送
- 自定义Django的admin界面
- axios 讲解 和vue搭建使用