[BZOJ1584] [Usaco2009 Mar]Cleaning Up 打扫卫生(DP)
不会啊,看了好久的题解才看懂 TT
因为可以直接分成n段,所以就得到一个答案n,求解最小的答案,肯定是 <= n 的,
所以每一段中的不同数的个数都必须 <= sqrt(n),不然就不是最小的答案
那么
f[i]表示前i个数的最有解
g[i]表示从当前位置开始,有i个不同的数,最多能往前延伸到哪里
pre[i]表示上一个数为i的位置
cnt[i]表示g[i] + 1 ~ 当前位置 中的不同数的个数
所以 f[i] = min(f[i], f[g[j]] + j * j)
那么问题就是g数组的更新
如果 pre[x] > g[x],说明新的数在g[x] + 1 ~ 当前位置 中就包含了,不用更新,
否则g[x]就一直向后删除,直到有一种数全部删除,也就是到pre[x] <= g[x]
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 40001
#define min(x, y) ((x) < (y) ? (x) : (y)) int n, m;
int a[N], pre[N], cnt[N], g[N], f[N];
//f[i]表示前i个的最优解,g[i]表示数量为i最多能向左延伸到哪 inline int read()
{
int x = 0, f = 1;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
return x * f;
} int main()
{
int i, j, k, x;
n = read();
m = read();
m = sqrt(n);
memset(f, 127, sizeof(f));
for(i = 1; i <= n; i++) a[i] = read();
f[0] = 0;
for(i = 1; i <= n; i++)
{
for(j = 1; j <= m; j++)
if(pre[a[i]] <= g[j]) cnt[j]++;
pre[a[i]] = i;
for(j = 1; j <= m; j++)
if(cnt[j] > j)
{
k = g[j] + 1;
while(pre[a[k]] > k) k++;
g[j] = k;
cnt[j]--;
}
for(j = 1; j <= m; j++)
f[i] = min(f[i], f[g[j]] + j * j);
}
printf("%d\n", f[n]);
return 0;
}
[BZOJ1584] [Usaco2009 Mar]Cleaning Up 打扫卫生(DP)的更多相关文章
- 【动态规划】bzoj1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
思路自然的巧妙dp Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分 ...
- 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]$表示$ ...
- bzoj1584 [Usaco2009 Mar]Cleaning Up 打扫卫生 动态规划+思维
Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的 ...
- DP经典 BZOJ 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
BZOJ 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 419 Solve ...
- BZOJ_1584_[Usaco2009 Mar]Cleaning Up 打扫卫生_DP
BZOJ_1584_[Usaco2009 Mar]Cleaning Up 打扫卫生_DP Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= ...
- bzoj 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生【dp】
参考:http://hzwer.com/3917.html 好神啊 注意到如果分成n段,那么答案为n,所以每一段最大值为\( \sqrt{n} \) 先把相邻并且值相等的弃掉 设f[i]为到i的最小答 ...
- [bzoj1587] [Usaco2009 Mar]Cleaning Up 打扫卫生
首先(看题解)可得...分成的任意一段中的不同颜色个数都<=根号n...不然的话直接分成n段会更优= = 然后就好做多了.. 先预处理出对于每头牛i,和它颜色相同的前一头和后一头牛的位置. 假设 ...
- 【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 打扫卫生
Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的 ...
随机推荐
- [Ubuntu]“ubuntu.sh: 113: ubuntu.sh:Syntax error: "(" unexpected ”报错解决方法
原因:有可能是兼容性问题 解决方法: 1.sudo dpkg-reconfigure dash 2.在弹出的窗口选择no
- Linux下的I/O复用
读书笔记 I/O复用使得程序能同时监听多个文件描述符,这对提高程序的性能至关重要. Linux下实现I/O复用的系统调用主要有select, poll, epoll. select: 用户通过3个参数 ...
- windows下jdk环境变量配置
JAVA_HOMEC:\Program Files\Java\jdk1.8.0_131 JMETER_HOMEC:\jmeter\jmeter3.2 CLASSPATH%JAVA_HOME%\lib; ...
- vba 时间
Sub tt1() Dim d1, d2 As Date d1 = #//# d2 = #//# Debug.Print "相隔" & (d2 - d1) & &q ...
- cocoapods学习
1.安装 http://stackoverflow.com/questions/16459028/rvm-install-error-running-requirements-osx-port-ins ...
- Maven项目报错:Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:2.5:clean (default-clea
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:2.5:clean (default-clean) ...
- idea 发布和本地测试问题
1.maven本地打包成jar 提示[错误: 找不到或无法加载主类]修改 配置maven ---->Runner---->VM Optins [-DarchetypeCatalog=loc ...
- Google Colab免费GPU使用教程(一)
一.前言 现在你可以开发Deep Learning Applications在Google Colaboratory,它自带免费的Tesla K80 GPU.重点是免费.免费!(国内可能需要tz) 这 ...
- 快学UiAutomator创建第一个实例
工具准备 一.准备好java环境(JDK)和安卓环境(SDK.ADT)jdk1.6+ \eclipse\SDK \ADT详情百度,安装java环境 二.打开eclipse 三.创建步骤: 右键新建== ...
- js获取当前日期、前一天、后一天的日期的例子
<script> function addByTransDate(dateParameter, num) { var translateDate = "", dateS ...