zoukankan      html  css  js  c++  java
  • [题解]luogu_P3195_玩具装箱toy(斜率优化

    设$f[i]$表示装$i$个玩具用的最小花费,

     原转移方程:$f[i]=min(f[j]+(sum[i]-sum[j]+i-(j+1)+L)^2$

    把与$i$和$j$相关的放到一起:$f[i]=min(f[j]+(sum[i]+i-(sum[j]+j+L+1))^2$

    不断化简:设$a[i]=sum[i]+i,b[i]=sum[i]+i+L+1$,

    则:$f[i]=min(f[j]+(a[i]-b[j])^2)$

    对于$k,j$,若$j$比$k$优,则有:

    $f[j]+(a[i])^2+(b[j])^2-2*(a[i])*(b[j])<=f[k]+(a[i])^2+(b[k])^2-2*(a[i])*(b[k])$

    化简:$f[j]-f[k]+(b[j])^2-(b[k])^2<=2*(b[j]-b[k])*(a[i])$

    写成斜率形式:$frac{f[j]-f[k]+(b[j])^2-(b[k])^2}{b[j]-b[k]}<=2*a[i]$

    $a[i],b[i]$都是递增的,可以直接斜率优化

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define ll long long
    using namespace std;
    const int maxn=50009;
    int n;
    ll l,f[maxn],s[maxn];
    int q[maxn],head,tail;
    
    inline ll checka(int j,int k){
        return f[j]-f[k]+(s[j]+j+l+1+s[k]+k+l+1)*(s[j]+j-s[k]-k);
    }
    inline ll checkb(int j,int k){
        return s[j]+j-s[k]-k;
    }
    int main(){
        scanf("%d%lld",&n,&l);
        for(int i=1;i<=n;i++)
        scanf("%lld",&s[i]);
        for(int i=1;i<=n;i++)s[i]+=s[i-1];
        head=tail=1;
        for(int i=1;i<=n;i++){
            while(head<tail && checka(q[head+1],q[head])<=2*(s[i]+i)*checkb(q[head+1],q[head]))head++;
            f[i]=f[q[head]]+(s[i]+i-s[q[head]]-q[head]-l-1)*(s[i]+i-s[q[head]]-q[head]-l-1);
            while(head<tail && checka(i,q[tail])*checkb(q[tail],q[tail-1])<=checka(q[tail],q[tail-1])*checkb(i,q[tail]))tail--;
            q[++tail]=i;
        }
        printf("%lld",f[n]);
    }
  • 相关阅读:
    Java 和因特网
    永久性
    在计算机编程中,一个基本的概念就是同时对多个任务加以控制
    违例控制:解决错误
    清除时的困境:由谁负责清除?
    集合库与方便使用集合
    单根结构
    集合与继承器
    对象的创建和存在时间
    抽象的基础类和接口
  • 原文地址:https://www.cnblogs.com/superminivan/p/11297707.html
Copyright © 2011-2022 走看看