BZOJ 3675: [Apio2014]序列分割 动态规划 + 斜率优化 + 卡精度

Code: 

#include<bits/stdc++.h> 
#define N 100006 
#define M 205 
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;  
int n,k,a[N],q[N];      
ll s[N],f[N],g[N]; 
double slope(int i,int j) 
{
    if(s[i]==s[j]) return -1e18; 
    return 1.00*((g[i]-s[i]*s[i])-(g[j]-s[j]*s[j]))/(s[j]-s[i]); 
}
int main()
{
    // setIO("input"); 
    int i,j; 
    scanf("%d%d",&n,&k);  
    for(i=1;i<=n;++i) scanf("%lld",&s[i]),s[i]+=s[i-1]; 
    for(j=1;j<=k;++j) 
    {
        int head=1,tail=0; 
        q[++tail]=0; 
        for(i=1;i<=n;++i) 
        {
            while(head<tail&&slope(q[head],q[head+1])<=s[i]) ++head; 
            f[i]=g[q[head]]+s[q[head]]*(s[i]-s[q[head]]);  
            while(head<tail&&slope(q[tail-1],q[tail])>=slope(q[tail],i)) --tail; 
            q[++tail]=i; 
        }
        memcpy(g,f,sizeof(g)); 
    }
    printf("%lld\n",f[n]); 
    //     for(int x=n,i=k;i>=1;--i) x=pre[x][i], printf("%d ",x); 
    return 0; 
}

  

posted @ 2019-07-06 13:22  EM-LGH  阅读(129)  评论(0编辑  收藏  举报