题解-[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 ...
随机推荐
- Linux上传递文件到另外一个Linux服务器
现在的项目由于安全的需要,测试服务器被设置不能直接连接,想要连接的话,只能先登录一个服务器,然后以这个服务器为跳板,去登录另外一台真正的 服务器,即使是测试环境也只能这样操作.只能是相对来说安全一些. ...
- readonly和disabled的区别!
Readonly只针对input(text / password)和textarea有效 Disabled对于所有的表单元素都有效 readonly接受值更改可以回传,disable接受改但不回传数据 ...
- Python_科学计算平台__pypi体系的numpy、scipy、pandas、matplotlib库简介
1.numpy--基础,以矩阵为基础的数学计算模块,纯数学 存储和处理大型矩阵. 这个是很基础的扩展,其余的扩展都是以此为基础. 快速学习入口 https://docs.scipy.org/doc/n ...
- Python 写入和读取Excel数据
写数据到csv文件里 一. 在本地盘符里新建一个Excel文档,然后另存为csv文件 二.打开PyCharm,新建一个Python File ,写入以下代码 import randomimport ...
- js替换div里的内容
<!DOCTYPE html><html><head><meta charset="utf-8"><title>< ...
- unctf2020 部分简单题题解
unctf2020 水一波简单题..菜狗前来报道..大佬轻喷..如果有时间做题就好了呜呜呜 misc 1.baba_is_you 题目告诉我们,了解png文件格式. 下载得到一张png格式的图片. 用 ...
- 修改pycharm中的flask项目名遇到的坑
曾修改过自己的项目名,并在settings中的解释器也更正过来了.然后执行pip list 报错: failed to create process. 解决方法如下: 到你的项目的venv目录下的Sc ...
- 从执行上下文角度重新理解.NET(Core)的多线程编程[2]:同步上下文
一般情况下,我们可以将某项操作分发给任意线程来执行,但有的操作确实对于执行的线程是有要求的,最为典型的场景就是:GUI针对UI元素的操作必须在UI主线程中执行.将指定的操作分发给指定线程进行执行的需求 ...
- pip更新报错问题
pip更新错误如下: WARNING: You are using pip version 20.1.1; however, version 20.2 is available. You should ...
- LinuxKernel(一)
首先,回顾一下基础的宏操作: C语言宏 #与## #的作用是字符串化:在一个宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组 #define ERROR_LOG(info) fprin ...