您的位置:首页 > 其它

[bzoj4518] [Sdoi2016]征途

2016-04-24 14:46 260 查看
  斜率优化。。因为要求方差乘m^2...也就是每段距离与平均值的平方和再乘m。

  f[i][j]表示i天后,走了j段的最小平方和。

  求出最小平方和再乘个m就行了= =

  需要注意,是可以停留在原地的。。。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#define d double
#define ll long long
using namespace std;
const int maxn=3023;
int i,j,k,n,m,now,pre,l,r;
ll pr[maxn],V[maxn];
int dl[maxn];
d f[2][maxn],v1[maxn];

int ra,fh;char rx;
inline int read() {
rx=getchar(),ra=0,fh=1;
while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
if(rx=='-')fh=-1,rx=getchar();
while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
}
inline d xl(int k1,int k2){//k1<k2
return (d)(f[pre][k2]-f[pre][k1]+V[k2]-V[k1])/(pr[k2]-pr[k1]);
}
inline d sqr(d x){return x*x;}
int main(){
n=read(),m=read();
for(i=1;i<=n;i++)pr[i]=pr[i-1]+read(),V[i]=pr[i]*pr[i];
d avg=(d)pr
/m;
for(i=0;i<=n;i++)f[0][i]=sqr(pr[i]-avg),v1[i]=(pr[i]-avg);
now=1,pre=0;
for(i=2;i<=m;i++,swap(now,pre)){
l=1,r=0;
for(j=0;j<=n;j++){
while(l<r&&xl(dl[r-1],dl[r])>=xl(dl[r],j))r--;
dl[++r]=j;
while(l<r&&2*v1[j]>=xl(dl[l],dl[l+1]))l++;
f[now][j]=f[pre][dl[l]]+sqr(v1[j]-pr[dl[l]]);
}
}
printf("%lld\n",(ll)(f[pre]
*m+0.5));
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: