题解-[SDOI2016]征途
[SDOI2016]征途
给定长度为 \(n\) 的序列 \(a\{n\}\),将其分为连续 \(m\) 段,和分别为 \(v\{m\}\)。\(v\{m\}\) 的方差为 \(E\),求 \(\left(m^2\times E\right)_{\min}\)。
\(1\le n\le 3000\),\(1\le \sum a_i\le 30000\)。
复习斜率优化第一题,遇到好多麻烦,写一篇题解记录。
首先推式探索 \(m^2\times E\) 的本质:
设 \(sum=\sum a_i=\sum v_i\)。
m^2\times E=&m^2\times \frac{\sum\limits_{i=1}^m\left(v_i-\frac{sum}{m}\right)^2}{m}\\
=&m \sum\limits_{i=1}^m\left(v_i-\frac{sum}{m}\right)^2\\
=&m \left(\sum\limits_{i=1}^mv_i^2-\sum\limits_{i=1}^m2v_i\cdot\frac{sum}{m}+\sum\limits_{i=1}^m\frac{sum^2}{m^2}\right)\\
=&m \left(\sum\limits_{i=1}^mv_i^2-2sum\cdot\frac{sum}{m}+m\cdot\frac{sum^2}{m^2}\right)\\
=&m \left(\sum\limits_{i=1}^mv_i^2-2\cdot\frac{sum^2}{m}+\frac{sum^2}{m}\right)\\
=&m \left(\sum\limits_{i=1}^mv_i^2-\frac{sum^2}{m}\right)\\
=&m \sum\limits_{i=1}^mv_i^2-sum^2\\
\end{split}
\]
很明显 \(-sum^2\) 是定值,所以要求 \(\left(m^2\times E\right)_{\min}\),应该先求 \(\left(\sum\limits_{i=1}^mv_i^2\right)_{\min}\)。
考虑到 \(n\) 很迷你,可以 \(\texttt{dp}\)。
\(F_{t,i}\) 表示前 \(t\) 段包含 \(a_1\sim a_i\) 的 \(\left(\sum\limits_{h=1}^tv_h^2\right)_{\min}\)。
假设 \(v_t=\sum_{h=j+1}^ia_h\)。
可以有递推式:
\]
如果 \(s_i=\sum\limits_{h=1}^ia_h\),用 \(f\) 表示 \(F_t\),用 \(g\) 表示 \(F_{t-1}\),那么上式变为:
\]
考虑 \(j=k\) 比 \(j=t\) 更优的情况:
g_k+(s_i-s_k)^2<& g_t+(s_i-s_t)^2\\
g_k+s_i^2-2s_is_k+s_k^2<& g_t+s_i^2-2s_is_t+s_t^2\\
g_k-2s_is_k+s_k^2<& g_t-2s_is_t+s_t^2\\
(g_k+s_k^2)-(g_t+s_t^2)<& 2s_is_k-2s_is_t\\
\frac{(g_k+s_k^2)-(g_t+s_t^2)}{s_k-s_t}<& 2s_i
\end{split}
\]
然后老套路,把 \((g_j,g_j+s_j^2)\) 当做点,单调队列维护一个下凸壳,实现 \(\texttt{dp}\)。
re int l,r; re vector<int> q(n+7);
for(re int i=1;i<=n;i++) dp[1][i]=p2(sm[i]);
for(re int t=2;t<=m;t++){
f=dp[t&1],g=dp[(t&1)^1],l=1,r=0,q[++r]=0; //奇淫技巧①:用指针 f,g 来定位滚动数组
for(re int i=1;i<=n;i++){
while(l<r&&slope(q[l],q[l+1])<=2.0*sm[i]) l++;
//奇淫技巧②:取min维护下凸壳,用<=,取max维护上凸壳,用>=
f[i]=g[q[l]]+p2(sm[i]-sm[q[l]]);
while(l<r&&slope(q[r-1],q[r])>=slope(q[r],i)) r--; //奇淫技巧③:递推前后两句话用不同比较符号
q[++r]=i;
}
}
最后的答案就是 \(m\cdot f_n-sum^2\)。
时间复杂度 \(\Theta(mn)\),空间复杂度 \(\Theta(n)\)。
Code
#include <bits/stdc++.h>
using namespace std;
//Start
#define re register
#define il inline
#define mk make_pair
#define pb push_back
#define db double
#define lng long long
#define fi first
#define se second
const int inf=0x3f3f3f3f;
const lng INF=0x3f3f3f3f3f3f3f3f;
//Data
const int N=3000; /* dp[i][j]:i-th day ***/
int n,m,dp[2][N+7],*f,*g; /** j-th section **/
vector<int> a,sm; /*** val min sum()^2 */
//DP
template<typename T>il T p2(re T x){return x*x;}
il db slope(re int x,re int y){ //斜率函数用double
return 1.0*((g[x]+p2(sm[x]))-(g[y]+p2(sm[y])))/(sm[x]-sm[y]);
}
il int DP(){
re int l,r; re vector<int> q(n+7);
for(re int i=1;i<=n;i++) dp[1][i]=p2(sm[i]);
for(re int t=2;t<=m;t++){
f=dp[t&1],g=dp[(t&1)^1],l=1,r=0,q[++r]=0;
for(re int i=1;i<=n;i++){
while(l<r&&slope(q[l],q[l+1])<=2.0*sm[i]) l++;
f[i]=g[q[l]]+p2(sm[i]-sm[q[l]]);
while(l<r&&slope(q[r-1],q[r])>=slope(q[r],i)) r--;
q[++r]=i;
}
}
return f[n];
}
//Main
int main(){
scanf("%d%d",&n,&m),a=sm=vector<int>(n+7);
for(re int i=1;i<=n;i++) scanf("%d",&a[i]),sm[i]=sm[i-1]+a[i];
printf("%d\n",m*DP()-p2(sm[n])); //别忘了求最终答案啊
return 0;
}
祝大家学习愉快!
题解-[SDOI2016]征途的更多相关文章
- 斜率优化入门学习+总结 Apio2011特别行动队&Apio2014序列分割&HZOI2008玩具装箱&ZJOI2007仓库建设&小P的牧场&防御准备&Sdoi2016征途
斜率优化: 额...这是篇7个题的题解... 首先说说斜率优化是个啥,额... f[i]=min(f[j]+xxxx(i,j)) ; 1<=j<i (O(n^2)暴力)这样一个式子,首 ...
- 【BZOJ4518】[Sdoi2016]征途 斜率优化
[BZOJ4518][Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除 ...
- bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)
题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地 ...
- 动态规划(决策单调优化):BZOJ 4518 [Sdoi2016]征途
4518: [Sdoi2016]征途 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 532 Solved: 337[Submit][Status][ ...
- BZOJ 4518: [Sdoi2016]征途 [斜率优化DP]
4518: [Sdoi2016]征途 题意:\(n\le 3000\)个数分成m组,一组的和为一个数,求最小方差\(*m^2\) DP方程随便写\(f[i][j]=min\{f[k][j-1]+(s[ ...
- bzoj4518[Sdoi2016]征途 斜率优化dp
4518: [Sdoi2016]征途 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1657 Solved: 915[Submit][Status] ...
- BZOJ_4518_[Sdoi2016]征途_斜率优化
BZOJ_4518_[Sdoi2016]征途_斜率优化 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到 ...
- luoguP4072 [SDOI2016]征途
[SDOI2016]征途 大体 大概就是推推公式,发现很傻逼的\(n^3\)DP get60 进一步我们发现状态不能入手,考虑优化转移 套个斜率优化板子 每一层转移来一次斜率优化 思路 先便便式子 \ ...
- BZOJ4518 Sdoi2016 征途 【斜率优化DP】 *
BZOJ4518 Sdoi2016 征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m ...
随机推荐
- 适用初学者的5种Python数据输入技术
摘要:数据是数据科学家的基础,因此了解许多加载数据进行分析的方法至关重要.在这里,我们将介绍五种Python数据输入技术,并提供代码示例供您参考. 数据是数据科学家的基础,因此了解许多加载数据进行分析 ...
- psycopg2模块安装问题
我的平台是win10(x64).python3.7,打算通过psycopg2模块来操作Greenplum数据库,我通过pip install psycopg2 安装了psycopg2模块,也提示安装成 ...
- Python_PyQt5_eric6 做省市县筛选框
eric是PyQt5的图形化编辑工具,界面如下(另存为-桌面 查看大图) 下面是用eric6制作的 省市县 三级联动筛选框 (效果图+源码) 1 # -*- coding: utf-8 -*- 2 ...
- elementui checkbox复选框实现层级联动
使用elementui 实现复选框的层级联动,可能我的表述不准确,先上一个效果图. 实际开发中可能遇到这样的场景,当选择高一层级的复选框时它包含的低级的复选框就不需要再勾选,需要默认选中并且禁止选用. ...
- spring-boot-starter-parent和spring-boot-dependencies
如何创建一个SpringBoot项目,SpringBoot的依赖引入都是基于starter的,通常创建一个SpringBoot项目都是通过继承关系指定pom文件中的parent. <parent ...
- 新鲜出炉!阿里巴巴,京东,美团面经汇总,已拿offer!
最近在后台收到了很多小伙伴的私信,说自己最近想好好准备一下,在不久后的秋招跳个槽往大厂冲击一下,想要我给大家整理出一份大厂面试题好用来做好准备.之前公司有点事比较忙就没回私信.最近好一点了我也是立马联 ...
- C语言讲义——内存管理
动态分配内存 动态分配内存,在堆(heap)中分配. void *malloc(unsigned int num_bytes); 头文件 stdlib.h或malloc.h 向系统申请分配size个字 ...
- sentinel快速入门
转载:https://blog.csdn.net/noaman_wgs/article/details/103328793 https://github.com/alibaba/Sentinel/wi ...
- dubbo起停之服务暴露
由上一节可知带上dubbo@Service注解的对象,在注册成为bean之后会进一步注册一个ServiceBean,服务暴露便是在这里 public void afterPropertiesSet() ...
- wsgi_uwsgi_nginx
1.一些重要概念 https://www.cnblogs.com/xiaonq/p/8932266.html 1.1 web容器 什么是web容器 1.web容器是帮助我们部署java.php.pyt ...