[APIO2014]序列分割

Posted siruiyang_sry

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[APIO2014]序列分割相关的知识,希望对你有一定的参考价值。

link

其实可以发现我们选择切的顺序可以颠换。所以我们可以设$dp(i,j)$表示为前i个共切j的最大得分,然后$dp(i,j)=max(dp(i-1,z)+s[z] imes (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
",f[k][n]); 
    for(int i=k;i>=1;i--){
        printf("%d ",last[i][r]);
        r=last[i][r];
    }
}
View Code

 

以上是关于[APIO2014]序列分割的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3675: [Apio2014]序列分割

bzoj 3675 [Apio2014]序列分割(斜率DP)

[APIO2014]序列分割

3675: [Apio2014]序列分割

bzoj3675[Apio2014]序列分割 斜率优化dp

[APIO2014]序列分割 --- 斜率优化DP