bzoj3675: [Apio2014]序列分割

bzoj3675: [Apio2014]序列分割
二维斜率优化DP。


题解

首先手算一下就会发现,对于某种分割方法,计算顺序不影响结果。既然这样可以简化成简单DP。考虑f[i][j]表示前i个数分割j次的最大值,s[i]维护从1到i的前缀和,则f[i][j]=min(f[k][j-1]+s[k]*(s[i]-s[k]))。上斜率优化即可。另外,因为0会导致点重合,所以输入的时候忽略0。


代码
#include<iostream>
#include<cstdio>
#define mxn 100005
#define LL long long
using namespace std;
int q[mxn][2],i,k,h=1,t,t2,pre,n,now=1;
LL g[mxn][2],d[mxn][2],s[mxn],tp;
LL mul(LL y1,LL y2,LL x1,LL x2)
{return x1*y2-x2*y1;}
int main()
{
    scanf("%d%d",&n,&k);
    while(n--)
    {
        scanf("%lld",&tp);
        if(tp){q[++t][0]=t,s[t]=tp+s[t-1],g[t][0]=s[t]*s[t];}
    }
    n=t;
    while(k--)
    {
        for(i=1;i<=n;i++)
        {
            while(h<t&&q[h+1][pre]<i&&g[h+1][pre]-g[h][pre]<s[i]*(s[q[h+1][pre]]-s[q[h][pre]]))
            h++;
            tp=q[h][pre];
            d[i][now]=d[tp][pre]+s[tp]*(s[i]-s[tp]);
            tp=s[i]*s[i]-d[i][now];
            while(t2&&mul(tp-g[t2-1][now],g[t2][now]-g[t2-1][now],
            s[i]-s[q[t2-1][now]],s[q[t2][now]]-s[q[t2-1][now]])>0)t2--;
            g[++t2][now]=tp,q[t2][now]=i;
        }
        swap(now,pre),t=t2,t2=0,h=1;
    }
    printf("%lld\n",d[n][pre]);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值