APIO2014序列分割bzoj3675

来源:互联网 发布:淘宝新品标 编辑:程序博客网 时间:2024/06/07 06:22

最开始输出98,最开始赶脚是窝姿势不对……偷偷瞄了一眼黄学长的blog感觉get了新姿势,怒码,然后还是98……最后居然是窝括号的位置放错了……过于隐蔽肉眼没能debug出来QAQQQQQQQQQQ……还是太弱了……

这题很显然窝们可以写出Dp方程分程f[i]=f[j]+s[j]*(s[i]-s[j]),因为这题实际上和切的顺序是无关的,其实这很显然证明就是对于答案中的每一个区间必然会被乘上k?次(随便脑补了一下并没有实际计算),然后窝们就可以灰常高兴地写斜率优化啦

当年斜率DP专题比赛怒AK的RP哪去了QAQQQQQQQQQQQ

#include<cstdio>#include<cstring>#include<algorithm>#define N 100005#define LL long longusing namespace std;LL sum[N],f[N],q[N],a[N],g[N];int n,k;LL read(){LL x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x;}double calc(int j,int k){        return (double)(sum[k]*sum[k]-sum[j]*sum[j]-g[k]+g[j])/(double)(sum[k]-sum[j]);}void work(int x){        int h=1,t=0;        for (int i=x;i<=n;i++)        {                while (h<t&&calc(q[t-1],q[t])>calc(q[t],i-1)) t--;q[++t]=i-1;                while (h<t&&calc(q[h],q[h+1])<sum[i]) h++;int p=q[h];                f[i]=g[p]+(sum[i]-sum[p])*sum[p];        }        for (int i=x;i<=n;i++) swap(f[i],g[i]);}void dp(){        for (int i=1;i<=k;i++)                work(i);        printf("%lld\n",g[n]);}int main(){        n=read();k=read();        for (int i=1;i<=n;i++)                a[i]=read();        int top=0;for(int i=1;i<=n;i++)                if(a[i]!=0)        a[++top]=a[i];n=top;for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];dp();return 0;}


0 0