zoukankan      html  css  js  c++  java
  • [HNOI2008]玩具装箱TOY

    洛谷题目链接

    动态规划$+$单调队列$+$斜率优化

    身为$dp$蒟蒻的我,准备学斜率优化和单调队列,自然不能放过这个经典题目了,我们对于这题很容易想出一个暴力式子:

    ($sum[i]$为前缀和)

    $f[i]=min(f[i],f[j]+(sum[i]-sum[j]+i-j-L-1)^2)$

    我们不考虑最小值,把$sum[i]+i$用$a[i]$代替,$sum[j]+j+L+1$用$b[j]$代替,那么式子整理一下如下:

    $f[i]=f[j]+(a[i]+b[j])^2$

    去括号:

    $f[i]=f[j]+a[i]^2+2a[i]b[j]+b[j]^2$

    移项:

    $f[j]+b[j]^2=2a[i]b[j]+f[i]+a[i]^2$

    设$y=f[j]+b[j]^2$,$x=b[j]$,$b=f[i]+a[i]^2$,这就很像一次函数了,那么斜率自然就是$k=2a[i]$了

    为什么这么设呢,因为我们发现$y,x,k$在知道$i,j$时可以快速求出

    $f[i]$的含义转化为:当上述直线过点$P(b[j],f[j]+b[j]^2)$时,直线在$y$轴的截距加上$a[i]^2$(一个定值)

    而题目即为找这个截距的最小值

    而且我们仔细一看发现会有单调性,于是用单调队列维护最小值。

    代码如下:

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #define N 50007
    #define int long long
    using namespace std;
    int n,L;
    int sum[N],que[N],f[N];
    int A(int i)
    {
    	return sum[i]+i;
    }
    int B(int i)
    {
    	return sum[i]+i+1+L;
    }
    int X(int i)
    {
    	return B(i);
    }
    int Y(int i)
    {
    	return f[i]+B(i)*B(i);
    }
    int Get_k(int i,int j)
    {
    	return (Y(i)-Y(j))/(X(i)-X(j));
    }
    signed main()
    {
    	scanf("%lld%lld",&n,&L);
    	for(int i=1;i<=n;++i)
    	{
    		scanf("%lld",&sum[i]);
    		sum[i]+=sum[i-1];
    	}
    	int head=1,tail=1;
    	for(int i=1;i<=n;++i)
    	{
    		while(head<tail&&Get_k(que[head],que[head+1])<2*A(i))
    			++head;
    		f[i]=f[que[head]]+(A(i)-B(que[head]))*(A(i)-B(que[head]));
    		while(head<tail&&Get_k(que[tail],que[tail-1])>Get_k(i,que[tail-1]))
    			--tail;
    		que[++tail]=i;
    	}
    	printf("%lld",f[n]);
    	return 0;
    }
    

      

  • 相关阅读:
    《活着》--余华
    《麦田里的守望者》--[美]杰罗姆·大卫·塞林格
    《平凡的世界》--路遥
    彩色照片转换为黑白照片(Color image converted to black and white picture)
    《戴尔·卡耐基传记》--[美]戴尔·卡耐基
    Maven的第一个小程序
    C# RabbitMQ优先级队列实战项目演练
    控制WinForm中Tab键的跳转
    C#模板引擎NVelocity实战项目演练
    C#隐藏手机号中间四位为*
  • 原文地址:https://www.cnblogs.com/yexinqwq/p/10214547.html
Copyright © 2011-2022 走看看