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]);
    }
  • 相关阅读:
    - 错误笔记
    只是一个没有人知道的蒟蒻
    省选前模板复习
    数学知识小结#1
    写在NOIP2018后
    Atcoder&CodeForces杂题11.7
    Atcoder&CodeForces杂题11.6
    [NOIP11.1模拟赛]补番报告
    [JZOJ5281]钦点题解--瞎搞+链表
    [JZOJ5280]膜法师题解--思维+前缀和
  • 原文地址:https://www.cnblogs.com/superminivan/p/11297707.html
Copyright © 2011-2022 走看看