【算法】DP+数学优化

【题意】把n个1~m的数字分成k段,每段的价值为段内不同数字个数的平方,求最小总价值。n,m,ai<=40000

【题解】

参考自:WerKeyTom_FTD

令f[i]表示把前i个数分成若干段的最小价值。

转移中我们定义,从i开始往前到有j个不同的数的最小位置为b[j]。

f[i]=f[b[j]-1]+j^2。

考虑最坏情况,每个数自成一段,则总价值为n。

所以当段内不同的数个数>√n时,就不可能是最优解了(此时价值>n)。

所以f[i]=f[b[j]-1]+j^2,1<=j<=√n。

快速计算的关键在递推b[j]数组,首先在递推过程中同步计算上一个等数位置last[]和桶c[]。

枚举j:

如果last[i]>=b[j],不会新增数,不改变。

否则,b[j]++直到c[a[b[j]]]=b[j],此时b[j]++得到新的b[j]。

注意若元素个数不满√n个,出现新元素就top++。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=; int n,N,a[maxn],last[maxn],c[maxn],b[maxn],f[maxn],m,top;
int main(){
scanf("%d%d",&n,&N);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
m=(int)sqrt(n)+;
top=;
for(int i=;i<=n;i++){
last[i]=c[a[i]];
c[a[i]]=i;
for(int j=;j<=min(m,top);j++)if(last[i]<b[j]){
while(c[a[b[j]]]!=b[j])b[j]++;
b[j]++;
}
if(!last[i])b[++top]=;
f[i]=i;
for(int j=;j<=min(m,top);j++)f[i]=min(f[i],f[b[j]-]+j*j);
}
printf("%d",f[n]);
return ;
}

【BZOJ】1584: [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 打扫卫生

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

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

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

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

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

  5. 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]$表示$ ...

  6. [bzoj1587] [Usaco2009 Mar]Cleaning Up 打扫卫生

    首先(看题解)可得...分成的任意一段中的不同颜色个数都<=根号n...不然的话直接分成n段会更优= = 然后就好做多了.. 先预处理出对于每头牛i,和它颜色相同的前一头和后一头牛的位置. 假设 ...

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

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

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

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

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

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

随机推荐

  1. 对编码内容多次UrlDecode

    对编码内容多次UrlDecode,并不会影响最终结果. 尝试阅读了微软的源代码,不过不容易读懂. 网址:https://referencesource.microsoft.com/#System/ne ...

  2. 基于gulp的前端自动化开发构建新

    关于gulp的使用,已经在之前写过一篇文章,但是遗留了一个问题.问题是实现文件的增量式更新,就是给html引入的js和css文件打上标记.每次更新标记更新. 上篇文章想通过开发同时实现标记的实时更新, ...

  3. C#窗口文件双击打开时出错

    出错原因: 1. 修改了该窗口文件的.Designer.cs文件中:#region Windows 窗体设计器生成的代码这里面的代码,导致运行不正常. 为了传递数据,我在构造函数中增加了传递的值. 需 ...

  4. Matlab画平滑曲线的两种方法

    自然状态下,用plot画的是折线,而不是平滑曲线. 有两种方法可以画平滑曲线,第一种是拟合的方法,第二种是用spcrv,其实原理应该都一样就是插值.下面是源程序,大家可以根据需要自行选择,更改拟合的参 ...

  5. NOI 97 (Vijos 1464)积木游戏(DP)

    很普通的DP,设dp[i][j][k]为第i块积木放在第j堆且摆放状态为k的最高高度.方程很容易推出. # include <cstdio> # include <cstring&g ...

  6. Luogu1041 NOIP2003传染病控制(搜索)

    暴搜加个最优性剪枝即可.一直觉得正式比赛出这种不能一眼看出来暴搜就行了的搜索题的出题人都是毒瘤. #include<iostream> #include<cstdio> #in ...

  7. BZOJ5329: [SDOI2018]战略游戏——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5329 https://www.luogu.org/problemnew/show/P4606 省选 ...

  8. GDI & GDI+

    GDI GDI绘图中的映射模式CDC::SetMapMode() GDI编程小结 GDI+ GDI+小例子 关于GDI+ GDI+编程小结

  9. 【枚举】 最大子矩阵(I)

    题注:最大子矩形问题的解决办法最初由中国国家集训队王知昆前辈整理并发表为论文,在此说明并感谢. Definition 给你一个大矩形,里面有一些障碍点,求一个面积最大的矩形,满足该矩形在大矩形内部且该 ...

  10. 一篇博文将JavaScript尽收眼底

    简介 这篇文章是为专业程序员介绍的JavaScript语言的,它是一种小巧的语言,如果你熟悉其他的编程语言,那么这篇文章对你来讲不是那么难以理解. JavaScript不是Java,他们是两门完全不同 ...