[BZOJ3675][Apio2014]序列分割(斜率优化dp)

题目描述

传送门

题解

感觉有点不在状态。。。
转移方程: f[i][j]=max{f[i1][k]+(s[j]s[k])(s[n]s[j])}
显然可以斜率优化。

代码

#include
#include
#include
using namespace std;
#define LL long long
const int max_n=1e5+5;

int n,m,head,tail;
int q[max_n];
LL x,f[max_n],g[max_n],s[max_n];

inline LL K(int k){return s[k];}
inline LL B(int k){return g[k]-s[k]*s[n];}
inline LL Y(int j,int k){return K(k)*s[j]+B(k);}
inline bool cmp(int x1,int x2,int x3){
    LL w1=(K(x1)-K(x3))*(B(x2)-B(x1));
    LL w2=(K(x1)-K(x2))*(B(x3)-B(x1));
    return w1>=w2;
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i) scanf("%lld",&x),s[i]=s[i-1]+x;
    for (int i=1;i<=m;++i){
        head=tail=0;
        for (int j=0;j<=n;++j){
            while (headq[head])<=Y(j,q[head+1])) head++;
            f[j]=Y(j,q[head])+s[j]*s[n]-s[j]*s[j];
            while (headq[tail-1],q[tail])) tail--;
            q[++tail]=j;
        }
        for (int j=0;j<=n;++j) g[j]=f[j]/*,printf("%d %d:%d\n",i,j,g[j])*/;
    }
    LL ans=0;
    for (int i=1;iprintf("%lld\n",ans);
}

你可能感兴趣的:(题解,dp)