• Luogu P3195 [HNOI2008]玩具装箱


    题目
    预处理(C)的前缀和(sum)。设前(i)个物品的最小答案为(f)
    (f_i=maxlimits_{jin[1,i)}(f_j+(sum_i-sum_j-L)^2))
    拆开就是(f_i=maxlimits_{jin[1,i)}(f_j+sum_i^2+sum_j^2+L^2-2Lsum_i-2Lsum_j-2sum_isum_j))
    稍微整理一下(f_i=maxlimits_{jin[1,i)}(f_j+sum_j^2-2Lsum_j-2sum_isum_j)+sum_i^2+L^2-2Lsum_i)
    然后直接斜率优化。
    代码是以前写的,建议斜率交叉相乘后判断大小避免精度误差。

    #include<bits/stdc++.h>
    #define N 50001
    using namespace std;
    inline int read()
    {
        int x=0;
        char ch=getchar();
        while(ch<'0'||ch>'9')
            ch=getchar();
        while(ch>='0'&&ch<='9')
            x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
        return x;
    }
    inline int max(int a,int b)
    {
    	return a>b? a:b;
    }
    long long sum[N],f[N],q[N],L;
    inline double slope(int i,int j)
    {
    	return (double)(f[i]-f[j]+(sum[i]-sum[j])*(sum[i]+sum[j]+(L<<1)))/(double)(sum[i]-sum[j]);
    }
    int main()
    {
    	register int n=read();
    	L=read()+1;
    	for(register int i=1;i<=n;++i)
    		sum[i]=sum[i-1]+read()+1;
    	register int hd=1,tl=1;
    	for(register int i=1;i<=n;++i)
    	{
    		while(hd<tl&&slope(q[hd],q[hd+1])<2*sum[i])
    			++hd;
    		f[i]=f[q[hd]]+(sum[i]-sum[q[hd]]-L)*(sum[i]-sum[q[hd]]-L);
            while(hd<tl&&slope(i,q[tl-1])<slope(q[tl-1],q[tl]))
    			--tl;
            q[++tl]=i;
        }
        return printf("%lld",f[n]),0;
    }
    
  • 相关阅读:
    Go语言基础之map
    Go语言基础之切片
    Go语言基础之数组
    Go语言fmt.Printf使用指南
    Go语言基础之流程控制
    Go语言基础之运算符
    Go语言基础之变量和常量
    Go语言环境搭建
    随笔
    使用SocketServer 创建TCP服务端
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11749595.html
Copyright © 2020-2023  润新知