APIO2014序列分割bzoj3675

最开始输出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 long
using 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值