题解-[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 ...
随机推荐
- 使用Ganglia监控系统监控集群(debian)
ganglia是一个集群监控软件,底层使用RRDTool获得数据. Ganglia分为ganglia-monitor和gmetad两部分,前者运行在集群每个节点上(被监控机器)收集RRDTool产生的 ...
- SQL Server 数据库bak备份文件还原操作和mdf文件附加操作
前言:现在任何软件都离不开数据的支持,数据的价值是无价的,因此数据目前显得尤为重要,日常软件生产库的数据定时或实时备份必不可少,备份出的文件也需要进行验证,下边我将介绍SQL Server数据的的备份 ...
- [LeetCode题解]143. 重排链表 | 快慢指针 + 反转
解题思路 找到右边链表,再反转右边链表,然后按左.右逐一合并 代码 /** * Definition for singly-linked list. * public class ListNode { ...
- 统计数字问题(Java)
Description 一本书的页码从自然数1 开始顺序编码直到自然数n.书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0.例如,第6 页用数字6 表示,而不是06 或006 等.数字计数问 ...
- Linux下查询外网IP的办法。
Curl 纯文本格式输出:curl icanhazip.comcurl ifconfig.mecurl curlmyip.comcurl ip.appspot.comcurl ipinfo.io/ip ...
- 数据丢失如何恢复?EasyRecovery帮你快速实现
在日常使用电脑时,我们经常会遇到误删文件的情况,若文件还未被彻底删除,我们还可以通过电脑中的回收站将其恢复,但若是回收站都被清空的话,想要恢复文件就变得比较困难了,而EasyRecovery可以很好的 ...
- tcp连接的三次握手
为什么tcp连接需要三次握手才能建立连接 主要是为了初始化sequence number的初始值,通信的双方要互相通知双方的sequence number,这个要作为以后数据通信的序号,保证以后不会因 ...
- linux(cemtos7.x)安装docker
卸载旧版本 yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest ...
- 第四章:动态规划I
4.1背包问题 动态规划的核心:如何构造一个高效的备忘录,提高整个问题求解的效率. 4.2最大子数组问题II
- 聊聊 传统IO和网络IO
IO 模型 传统 IO读写 磁盘IO主要的延时是由(以15000rpm硬盘为例): 机械转动延时(机械磁盘的主要性能瓶颈,平均为2ms) + 寻址延时(2~3ms) + 块传输延时(一般 ...