点此看题面

大致题意: 让你把一个长度为\(n\)的序列划分成\(m\)块,求每块数总和的最小方差乘\(m^2\)的值。

转化方差

首先方差显然是一个比较复杂的东西,需要进行一定转化。

设\(p_i\)为第\(i\)块数总和;\(s_i\)为原序列的前缀和,即\(s_i=\sum_{i=1}^ia_i\);\(\bar p\)为\(p_i\)的平均值,即\(\bar{p}=\frac{\sum_{i=1}^mp_i}m=\frac{s_n}m\)。

然后推式子:

\[m^2*\frac{\sum_{i=1}^m(p_i-\bar{p})^2}m=m\sum_{i=1}^m(p_i^2-2p_i\bar{p}+\bar{p}^2)=m\sum_{i=1}^mp_i^2-2m\bar{p}\sum_{i=1}^mp_i+m^2\bar{p}^2
\]

其中\(\sum_{i=1}^mp_i\)显然就是\(s_n\),同时我们把\(\bar{p}\)的值代入得到:

\[m\sum_{i=1}^mp_i^2-2s_n^2+s_n^2=m\sum_{i=1}^mp_i^2-s_n^2
\]

动态规划

考虑上面这个式子,其中\(m,s_n^2\)都是常数,因此我们只需要最小化\(p_i\)平方和。

可以考虑动态规划

设\(f_{i,j}\)表示当前第\(i\)位,已划分出\(j\)块时的\(p_i\)平方和的最小值。

显然暴力转移只需枚举一个转移点:

\[f_{i,j}=\min_{x=1}^{i-1}(f_{x,j-1}+(s_i-s_x)^2)
\]

这就是\(O(n^3)\)的做法了。

斜率优化

显然上面的\(DP\)还不够优,需要优化。

这里我们考虑斜率优化。

设当前为\(i\),比较对于\(a\)和\(b\)两个转移点,若我们选择\(a\)进行转移,则需要满足:

\[f_{a,j-1}+(s_i-s_a)^2<f_{b,j-1}+(s_i-s_b)^2
\]

拆平方并移项:

\[2s_i(s_b-s_a)<(f_{b,j-1}+s_b^2)-(f_{a,j-1}+s_a^2)
\]

两边同除以\(s_b-s_a\)得:

\[2s_i<\frac{(f_{b,j-1}+s_b^2)-(f_{a,j-1}+s_a^2)}{s_b-s_a}
\]

设\(A(x)=s_x,B(x)=f_{x,j-1}+s_x^2\),则上面的式子就相当于:

\[2s_i<\frac{B(b)-B(a)}{A(b)-A(a)}
\]

这是一个斜率的形式。

那么我们就可以开一个单调队列维护一个斜率逐渐上升的序列。

然后每次转移之前,将队首斜率小于\(2s_i\)的几项弹掉再转移即可。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 3000
#define INF 1e9
using namespace std;
int n,m,a[N+5],s[N+5],q[N+5],f[N+5][N+5];
int main()
{
RI i,j,H,T;for(scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%d",a+i),s[i]=s[i-1]+a[i];//读入+初始化前缀和
#define A(x) (s[x])
#define B(x) (f[x][j-1]+s[x]*s[x])
#define S(x,y) (1.0*(B(y)-B(x))/(A(y)-A(x)))
#define Slope (2.0*s[i])
for(i=1;i<=n;++i) f[i][0]=INF;//初始化
for(j=1;j<=m;++j) for(q[H=T=1]=0,i=1;i<=n;++i)//注意要先枚j
{
W(H<T&&Slope>=S(q[H],q[H+1])) ++H;//弹掉不合法队首
f[i][j]=f[q[H]][j-1]+(s[i]-s[q[H]])*(s[i]-s[q[H]]);//转移
W(H<T&&S(q[T-1],q[T])>=S(q[T-1],i)) --T;q[++T]=i;//保证单调递增,放入队尾
}return printf("%lld",1LL*m*f[n][m]-1LL*s[n]*s[n]),0;//输出答案
}

【BZOJ4518】[SDOI2016] 征途(重拾斜率优化DP)的更多相关文章

  1. [luogu4072][bzoj4518][SDOI2016]征途【动态规划+斜率优化】

    题目分析 Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m天外,每一天晚上Pine都必须在休息站过夜.所以,一段路 ...

  2. bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

    题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地 ...

  3. bzoj4518[Sdoi2016]征途 斜率优化dp

    4518: [Sdoi2016]征途 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1657  Solved: 915[Submit][Status] ...

  4. BZOJ4518 Sdoi2016 征途 【斜率优化DP】 *

    BZOJ4518 Sdoi2016 征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m ...

  5. 洛谷 P4072 [SDOI2016]征途 斜率优化DP

    洛谷 P4072 [SDOI2016]征途 斜率优化DP 题目描述 \(Pine\) 开始了从 \(S\) 地到 \(T\) 地的征途. 从\(S\)地到\(T\)地的路可以划分成 \(n\) 段,相 ...

  6. [SDOI2015][bzoj4518] 征途 [斜率优化dp]

    题面 传送门 思路 把$vm^2$展开化一下式子,可以得到这样的等价公式: $vm^2=m\sum_{i=1}^m a_i^2-\sum_{i=1}^m a_i$ 那么我们要最小化的就是$\sum_{ ...

  7. 斜率优化dp练习

    1.HDU3507 裸题,有助于理解斜率优化的精髓. dp[i]=min(dp[j]+m+(sum[i]-sum[j])2) 很显然不是单调队列. 根据斜率优化的的定义,就是先设两个决策j,k 什么时 ...

  8. 斜率优化dp 的简单入门

    不想写什么详细的讲解了...而且也觉得自己很难写过某大佬(大米饼),于是建议把他的 blog 先看一遍,然后自己加了几道题目以及解析...顺便建议看看算法竞赛(蓝皮书)的 0x5A 斜率优化(P294 ...

  9. 【洛谷3648/BZOJ3675】[APIO2014]序列分割(斜率优化DP)

    题目: 洛谷3648 注:这道题洛谷3648有SPJ,要求输出方案.BZOJ3675数据组数较多但不要求输出方案. 分析: 这可能是我第三次重学斜率优化了--好菜啊 这道题首先一看就是个DP.稍微推一 ...

随机推荐

  1. C语言中,字符型数字与常数型数字的加减实现

    char in-str[10],out-str[10]; for(int i=0;i<10;i++) { out-str[i]=9-(in-str[i]-'0')+'0'; }

  2. CF1254D Tree Queries(树链剖分)

    出题人的做法是 \(O(n\sqrt{n\log n})\),结果这场结束后就被狂喷,一群人给出了 \(O(n\sqrt{n})\) 做法,甚至 \(O(n\log n)\) 都出来了-- 首先发现, ...

  3. IT兄弟连 Java语法教程 数据类型转换

    类型转换是将一个值从一种类型更改为另一种类型的过程.例如,可以将String(字符串,字符串是Java中非常特殊的数据类型,字符串属于引用类型,但是可以像基本类型一样使用字面值赋值)类型数据“456” ...

  4. 【mysql报错】[Err] 1248 - Every derived table must have its own alias

    当我运行一条联合查询的sql语句时报如下错误: [Err] 1248 - Every derived table must have its own alias,大概意思是每一张派生表必须要有自己的别 ...

  5. 05-Django模型(2)

    1.特殊查询 F和Q查询: 之前的查询都是模型对象的属性与常量值比较,两个属性怎么比较呢?使用F查询. F查询语法: from django.db.models import F F('属性名称') ...

  6. CentOS 7 firewalld详解,添加删除策略

    一.CentOS7中firewall防火墙 修改防火墙配置文件之前,需要对之前防火墙[/etc/firewalld/zones/public.xml]做好备份 重启防火墙后,需要确认防火墙状态和防火墙 ...

  7. Python巧用法

    #for 与 else 搭配使用(使用break跳过else) a=[1,2,3,4,5] for i in a: print(i) else: print(i, 'I am else!') for ...

  8. jxl解析excel时,处理中文乱码问题

    jxl解析excel时,处理中文乱码问题 一般出现较多的问题是,当exce中包含了中文或特殊字符时,在解析时候就会出现乱码现象. 解决方法为: InputStream in = new FileInp ...

  9. 用ggplot包画一个简单饼图

    首先用library函数加载ggplot2包 library(ggplot2) library(dplyr) library(tidyr) library(splines) 接下来,进行数据准备: d ...

  10. django6-orm进阶操作

    1.创建django环境的脚本 在自定义脚本中操作orm ,但是自定义脚本中不具备django的环境 ###test.py 脚本,引入django的环境即可使用orm操作数据库import os if ...