DP经典 BZOJ 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
BZOJ 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 419 Solved: 278
Description
有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000。现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k。那总的不河蟹度就是所有段的不河蟹度的总和。
Input
第一行:两个整数N,M
第2..N+1行:N个整数代表每个奶牛的编号
Output
一个整数,代表最小不河蟹度
Sample Input
1
2
1
3
2
2
3
4
3
4
3
1
4
Sample Output
/*因为这个题目分组是没有限制的,所以我们DP方程不能把分组作为一个状态
正解:最差情况每个数位于一段,ans=n,所以若有一段区间内不同的数的数量<=sqrt(n),否则结果一定不是最优。
nsqrt(n)求法:维护b[j],c[j],f[j],pre[j]数组。
b[j]表示b[j]+1...i有j个不同的数的区间的最左端。
那么可以知道f[i]=min{f[i],f[b[j]]+j*j};这样时间复杂度就降了下来
如何维护b[j]数组,当i向后移动一位的时候,pre[a[i]]记录a[i]出现的最后一个位置是哪里?
那么:i++后,pre[a[i]]<=b[j],说明b[j]+1...到i这段序列的不同数的数目就是j+1了,我们用c[j]来记录这个情况,顺便更新pre[a[i]],而且始终维护c[j]==j;
那么b[j]仍然是符合题意的。
维护c[j]就要从b[j]+1开始向后面删除数据,删除时判断若pre[a[t]]>t,则说明是删除了相同的数,对于最后的和谐值没有影响,所以还要删数
知道pre[a[t]]<=t,删除a[t],顺便更新b[j]的位置
*/
#define N 40100
#include<iostream>
using namespace std;
#include<cstdio>
#include<cmath>
#include<cstring>
int f[N],b[N],c[N],pre[N],a[N];
int n,m;
void input()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
scanf("%d",&a[i]);
memset(pre,-,sizeof(pre));/*别忘了设置为-1,因为下面会与b[j]==0的初值进行比较*/
memset(f,,sizeof(f));
}
void chuli()
{
int sqrtn=sqrt(n+0.5);
f[]=;/*初始化,前0个数的不和谐值为0,*/
for(int i=;i<=n;++i)
{
for(int j=;j<=sqrtn;++j)
{
if(pre[a[i]]<=b[j])
c[j]++;/*统计新加入的数是不是符合要求*/
}
pre[a[i]]=i;/*更新pre*/
for(int j=;j<=sqrtn;++j)
{
if(c[j]>j)/*删除数,缩短序列*/
{
int t=b[j]+;
while(pre[a[t]]>t) ++t;
b[j]=t;c[j]--;
}
}
for(int j=;j<=sqrtn;++j)
f[i]=min(f[i],f[b[j]]+j*j);/*更新f*/
}
}
int main()
{
input();
chuli();
cout<<f[n]<<endl;
return ;
}
/*这个题目既然不以划分次数为状态,那么可以考虑,划分序列的长度*/
DP经典 BZOJ 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生的更多相关文章
- bzoj 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生【dp】
参考:http://hzwer.com/3917.html 好神啊 注意到如果分成n段,那么答案为n,所以每一段最大值为\( \sqrt{n} \) 先把相邻并且值相等的弃掉 设f[i]为到i的最小答 ...
- bzoj:1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的 ...
- 【BZOJ】1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
[算法]DP+数学优化 [题意]把n个1~m的数字分成k段,每段的价值为段内不同数字个数的平方,求最小总价值.n,m,ai<=40000 [题解] 参考自:WerKeyTom_FTD 令f[i] ...
- BZOJ_1584_[Usaco2009 Mar]Cleaning Up 打扫卫生_DP
BZOJ_1584_[Usaco2009 Mar]Cleaning Up 打扫卫生_DP Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= ...
- [BZOJ1584] [Usaco2009 Mar]Cleaning Up 打扫卫生(DP)
传送门 不会啊,看了好久的题解才看懂 TT 因为可以直接分成n段,所以就得到一个答案n,求解最小的答案,肯定是 <= n 的, 所以每一段中的不同数的个数都必须 <= sqrt(n),不然 ...
- 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]$表示$ ...
- [bzoj1587] [Usaco2009 Mar]Cleaning Up 打扫卫生
首先(看题解)可得...分成的任意一段中的不同颜色个数都<=根号n...不然的话直接分成n段会更优= = 然后就好做多了.. 先预处理出对于每头牛i,和它颜色相同的前一头和后一头牛的位置. 假设 ...
- 【动态规划】bzoj1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
思路自然的巧妙dp Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分 ...
- bzoj1584 [Usaco2009 Mar]Cleaning Up 打扫卫生 动态规划+思维
Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的 ...
随机推荐
- python作业购物车(第二周)
一.作业需求: 1.启动程序后,输入用户名密码后,如果是第一次登录,让用户输入工资,然后打印商品列表 2.允许用户根据商品编号购买商品 3.用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒 4 ...
- perl6 登录phpmyadmin
use HTTP::UserAgent; my $ua = HTTP::UserAgent.new; my $url = 'http://localhost/phpMyAdmin/index.php' ...
- flask插件系列之Flask-WTF表单
flask_wtf是flask框架的表单验证模块,可以很方便生成表单,也可以当做json数据交互的验证工具,支持热插拔. 安装 pip install Flask-WTF Flask-WTF其实是对w ...
- python设计模式之常用创建模式总结(二)
前言 设计模式的创建模式终极目标是如何使用最少量最少需要修改的代码,传递最少的参数,消耗系统最少的资源创建可用的类的实例对象. 系列文章 python设计模式之单例模式(一) python设计模式之常 ...
- PCA算法和SVD
如果矩阵对某一个向量或某些向量只发生伸缩变换,不对这些向量产生旋转的效果,那么这些向量就称为这个矩阵的特征向量,伸缩的比例就是特征值.这里可以将特征值为负,特征向量旋转180度,也可看成方向不变,伸缩 ...
- mknod命令
mknod - make block or character special filesmknod [OPTION]... NAME TYPE [MAJOR MINOR] option 有用的 ...
- django的orm获取字段去重值
如果要用django的ORM获取一个表字段所有可能的去重值. 网上找了很多,都是用distinct关键字,但如何没有随后的order_by, 还是达不到要求的. 最后搞定. 参考URL http:// ...
- Java学习(if wihle switch for语句)
一.if语句 定义:if语句是指如果满足某种条件,就进行某种处理. 语句: if (条件语句){ 执行语句; …… } 上述格式中,判断条件是一个布尔值,当判断条件为true时,{}中的执行语句才会执 ...
- Cookie机制和Session机制
1. cookie 1. Cookie 是在HTTP协议下,服务器或脚本可以维护客户工作站上信息的一种方式.Cookie 是由 Web服务器保存在用户浏览器(客户端)上的小文本文件(内容通常经过加密) ...
- 使用matlab表示“段数不确定”的分段函数
示例函数: 分段函数f(x)的段数为数组a的长度减1,在表达f(x)时,不能直接使用a的长度5-1=4. 方法1: 先计算每个间隔点的函数值f(a2),f(a3),f(a4),再循环表示f(x). f ...