BZOJ 3675: [Apio2014]序列分割

Description

将一个序列切割\(k\)次,每次切割的收益是两边和的乘积,求最大收益.\(n\leqslant 1\times 10^5,k\leqslant 200\)

Solution

斜率优化DP..

因为什么\((a+b)c+ab=a(b+c)+bc\)..

所以他是只与结果有关的,跟切割方法无关,随便切就行...

\(f[i][j]=max\{f[k][j-1]+s[k](s[i]-s[k])\}\)

斜率正好是前缀和,并且单调不降..

所以直接斜率优化那一套就行了...

Code

/**************************************************************
    Problem: 3675
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:14596 ms
    Memory:84112 kb
****************************************************************/
 
#include <bits/stdc++.h>
using namespace std;
 
typedef long long LL;
const int N = 100005;
const int M = 205;
 
inline int in(int x=0,char ch=getchar()) { while(ch>'9'||ch<'0') ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();return x; }
 
int n,k;
int a[N],q[M][N],h[M],t[M];
LL s[N],f[N][2];
 
//#define B(i,j) (f[i][(j)&1]-s[i]*s[i])
//#define F(k,i,j) (B(k,((j)^1))+s[k]*s[i])
 
inline LL B(int i,int j) { return f[i][j&1]-s[i]*s[i]; }
inline LL F(int k,int i,int j) { return B(k,j^1)+s[k]*s[i]; }
 
int main() {
//  cout<<(sizeof(f)+sizeof(q)+sizeof(s)+sizeof(a))/1024.0/1024.0<<endl;
    n=in(),k=in();k++;
    for(int i=1;i<=n;i++) a[i]=in();
    for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
     
    for(int j=1;j<=k;j++) h[j]=1;
//  q[0][h[0]=t[0]=1]=0;
//  for(int i=1;i<=n;i++) f[i][1]=s[i];
    for(int j=2;j<=k;j++) {  
        q[j-1][h[j-1]=t[j-1]=1]=j-1;
        for(int i=j;i<=n;i++) {
            while(h[j-1]<t[j-1] && F(q[j-1][h[j-1]],i,j)<F(q[j-1][h[j-1]+1],i,j)) h[j-1]++;
            f[i][j&1]=F(q[j-1][h[j-1]],i,j);
//          cout<<i<<" "<<j<<" "<<q[j-1][h[j-1]]<<endl;
            while(h[j-1]<t[j-1] && 
                (s[q[j-1][t[j-1]]]-s[q[j-1][t[j-1]-1]])*(B(q[j-1][t[j-1]-1],j-1)-B(i,j-1))
                <=(s[i]-s[q[j-1][t[j-1]-1]])*(B(q[j-1][t[j-1]-1],j-1)-B(q[j-1][t[j-1]],j-1)))
                    t[j-1]--;
            q[j-1][++t[j-1]]=i;
        }
    }
//  for(int j=0;j<=1;j++) for(int i=1;i<=n;i++) printf("%lld%c",f[i][j]," \n"[i==n]);
    printf("%lld\n",f[n][k&1]);
    return 0;
}

  

posted @ 2017-04-18 16:45  北北北北屿  阅读(130)  评论(0编辑  收藏  举报