码迷,mamicode.com
首页 > Windows程序 > 详细

[APIO2014]序列分割

时间:2018-12-14 22:52:56      阅读:225      评论:0      收藏:0      [点我收藏+]

标签:ide   mes   \n   hide   span   signed   lap   def   ||   

link

其实可以发现我们选择切的顺序可以颠换。所以我们可以设$dp(i,j)$表示为前i个共切j的最大得分,然后$dp(i,j)=max(dp(i-1,z)+s[z] \times (s[i]-s[z])),s[i]=\sum_{i=1}^i  a_i$。

然后发现这是个斜率优化的式子,但是斜率只有一项,且为$dp(i,j)$,所以我们虽然是要去维护上凸壳但其实事实上维护下凸壳。然后就基本操作了

技术分享图片
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+c-0;c=getchar();}
    return f*ans;
}
const int N=100011;
const int K=211;
int f[K][N],n,k,s[N],last[K][N],que[N],dp[N],g[N],X[N],Y[N];
signed main(){
//    freopen("10.in","r",stdin);
    n=read(),k=read();
    for(int i=1;i<=n;i++) s[i]=s[i-1]+read();
    for(int p=1;p<=k;p++){
        int l,r;l=r=1;que[1]=0;
        for(int i=1;i<=n;i++) g[i]=f[p-1][i];
        Y[0]=s[0]*s[0]-g[0],X[0]=s[0];
        for(int i=1;i<=n;i++){
            while(l<r&&(Y[que[l+1]]-Y[que[l]])<=s[i]*(X[que[l+1]]-X[que[l]])) l++;
            f[p][i]=f[p-1][que[l]]+s[que[l]]*(s[i]-s[que[l]]);
            last[p][i]=que[l];
            X[i]=s[i],Y[i]=s[i]*s[i]-g[i];
            while(l<r&&(Y[que[r]]-Y[que[r-1]])*(X[i]-X[que[r]])>=(Y[i]-Y[que[r]])*(X[que[r]]-X[que[r-1]])) r--;
            que[++r]=i;
        }
    }
    int r=n;
    printf("%lld\n",f[k][n]); 
    for(int i=k;i>=1;i--){
        printf("%d ",last[i][r]);
        r=last[i][r];
    }
}
View Code

 

[APIO2014]序列分割

标签:ide   mes   \n   hide   span   signed   lap   def   ||   

原文地址:https://www.cnblogs.com/si-rui-yang/p/10121667.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!