bzoj 4518: [Sdoi2016]征途

16 篇文章 0 订阅
2 篇文章 0 订阅

题意:把n段路分成m天走,求每天走的路程的方差的最小值。输出方差*m^2。
题解:斜率优化
我们先推一推公式。

v×m2=mi=1(xix¯)2m×m2=i=1m(x2i2xix¯+x¯2)×m=i=1m(mx2i2xis)+sum2
然后直接搞就好了。
貌似可以划得更简= = 不管了反正能过
f[i][j]表示前i段路分成j天最小的 mi=1(mx2i2xis)
斜率:
f[k][o]f[j][o]+msum[k]sum[k]msum[j]sum[j]+2sum[n]sum[k]2sum[n]sum[j]sum[k]sum[j]2msum[i]

滚也懒的滚了。。。
代码:

#include<cstdio>
#include<cstring>

int n,m,a[3010],sum[3010],f[3010][3010],q[3010][3010],st[3010],ed[3010];

double slp(int k,int j,int o)
{
    return double(f[k][o]-f[j][o]+m*sum[k]*sum[k]-m*sum[j]*sum[j]+2*sum[n]*sum[k]-2*sum[n]*sum[j])/(sum[k]-sum[j]);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    for(int j=0;j<m;j++)
    {
        for(int i=1;i<=n;i++)
        {
            while(st[j]<ed[j]&&slp(q[j][st[j]],q[j][st[j]+1],j)<2*m*sum[i])
            st[j]++;
            int hh=q[j][st[j]],x=sum[i]-sum[hh];
            f[i][j+1]=f[hh][j]+m*x*x-2*sum[n]*x;
            while(st[j+1]<ed[j+1]&&slp(q[j+1][ed[j+1]-1],q[j+1][ed[j+1]],j+1)>slp(q[j+1][ed[j+1]],i,j+1))
            ed[j+1]--;
            q[j+1][++ed[j+1]]=i;
        }
    }
    printf("%d",f[n][m]+sum[n]*sum[n]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值