# SDOI征途--斜率优化

## 题解

### 准备部分

$S^2 = \frac{1}{m}*\sum_{i=1}^m(len_i - (\frac{1}{m}*\sum_{j=1}^{m}len_j) )^2$

$S^2 = \frac{1}{m}\sum_{i=1}^{m}len_i^2+\frac{1}{m}\sum_{i=1}^{m}\frac{1}{m^2}\sum_{j=1}^{m}len_j-2*\frac{1}{m}*\sum_{i=1}^{m}(len[i]*\frac{1}{m}\sum_{j=1}^{m}len_j)$

-->

$S^2 = \frac{1}{m}\sum_{i=1}^{m}len_i^2+\frac{1}{m^2}\sum_{i=1}^{m}len_i^2-2*\frac{1}{m^2}*(\sum_{i=1}^{m}len_i)*(\sum_{j=1}^{m}len_j)$

-->

$S^2 = \frac{1}{m}\sum_{i=1}^{m}len_i^2-\frac{1}{m^2}\sum_{i=1}^{m}len_i^2$

$m*\sum_{i=1}^{m}len_i^2-\sum_{i=1}^{m}len_i^2$

### 然后开始DP

$f[i][k] =f[j][k-1]+(\sum_{l=j+1}^{i}a[l])^2$

$f[i]=g[j]+(sum[i]-sum[j])^2$

### 斜率优化

$g[j]+sum[j]^2=-2*sum[i]*sum[j]+(sum[i]^2-f[i])$

$$g[j]+sum[i]^2$$ 看做 Y;
$$sum[i]$$ 看做 X;
$$-2*sum[i]$$ 看做 K;
$$(sum[i]^2-f[i])$$ 看做 B;

## 代码

#include<bits/stdc++.h>
using namespace std;
#define re register
#define in inline
#define get getchar()
#define ll long long
{
int t=0; char ch=get;
while(ch<'0' || ch>'9') ch=get;
while(ch<='9' && ch>='0') t=t*10+ch-'0', ch=get;
return t;
}
const int _=5001;
int n,m;
ll sum[_],f[_],g[_],q[_];
#define db double
in db  calc(int a,int b)
{
ll Y1=g[a]+sum[a]*sum[a],Y2=g[b]+sum[b]*sum[b];
return 1.0*(Y1-Y2)/(sum[a]-sum[b]);
}
int main()
{
for(re int i=1;i<=n;i++){
g[i]=sum[i]*sum[i];
}
for(re int k=2;k<=m;k++)
{
int l=1,r=0;
q[l]=0;q[0]=0;
for(re int i=1;i<=n;i++)
{
while(l<r && calc(q[l],q[l+1]) < 2*sum[i]) l++;
int j=q[l];
f[i]=g[j]+(sum[i]-sum[j])*(sum[i]-sum[j]);
while(l<r && calc(q[r],i) < calc(q[r-1],i)) r--;
q[++r]=i;
}
memcpy(g,f,sizeof(g));
}
cout<<m*f[n]-sum[n]*sum[n]<<endl;
}


posted @ 2019-11-01 19:41  yzhx  阅读(120)  评论(0编辑  收藏  举报