[BZOJ 3675][Apio2014]序列分割:DP斜率优化

点击这里查看原题

因为切割的位置相同时,顺序对结果没有影响,所以可以得到DP方程:f[i][j]=max{f[i-1][k]+(sum[n]-sum[j])*(sum[j]-sum[k])}
可以使用斜率优化,复杂度O(nk),外侧循环切割次数,内层循环切割位置。不过注意,因为空间只有128mb,因此要使用滚动数组。(如果在BZOJ上交出现了0ms的TLE,一定是因为MLE了)

/*
User:Small
Language:C++
Problem No.:3675
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
const int M=1e5+5;
int n,k,head,tail,que[M],p,q,cnt;
ll f[2][M],a[M],sum[M],ans;
double slop(int j,int k,int t){
    return (f[t][j]-f[t][k]+(sum[k]-sum[j])*sum[n])/(double)(sum[k]-sum[j]);
}
ll cal(int i,int j,int t){
    return f[t][j]+(sum[n]-sum[i])*(sum[i]-sum[j]);
}
int main(){
    freopen("data.in","r",stdin);//
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        if(a[i]!=0){
            a[++cnt]=a[i];
            sum[cnt]=sum[cnt-1]+a[i];
        }
    }
    n=cnt;
    p=0,q=1;
    for(int t=1;t<=k;t++){
        head=tail=0;
        for(int i=1;i<=n;i++){
            while(head<tail&&slop(que[head],que[head+1],p)<sum[i]) head++;
            f[q][i]=cal(i,que[head],p);
            while(head<tail&&slop(que[tail-1],que[tail],p)>slop(que[tail],i,p)) tail--;
            que[++tail]=i;
            if(t==k) ans=max(ans,f[q][i]);
        }
        swap(p,q);
    }
    printf("%lld\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值