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

    题意

    Here

    思考

    写的第一道斜率优化…感觉这个板题还蛮简单的

    首先按普通思路,我们令 (dp[i]),为前 (i) 个物品的最小价值,那么可以很容易列出方程:

    [dp[i] = min{ dp[j]+(sum[i]-sum[j]+i-j-1-L)^2 } ]

    这是一个 (O(n^2))(dp),我们考虑如何优化它:

    (s[x] = sum[x] + x, L=L+1),则

    [dp[i] = dp[j]+(sum[i]-sum[j]+i-j-1-L)^2 \ = dp[j] + (s[i] - s[j] - L) ^ 2 \ = dp[j] + s[i]^2 + (s[j]+L)^2 - 2*s[i]*(s[j]+L)]

    等式整理为:

    [dp[i] + 2 * s[i] * (s[j] + L) = dp[j] + s[i]^2 + (s[j] + L) ^ 2 ]

    在这个式子里面,我们把 (dp[j] + s[i]^2 + (s[j] + L)) 看作因变量, (s[j]+L)看作自变量,(dp[i]) 看作 (y) 轴截距,(2*s[i])(已知量)看作直线斜率,那么我们就是要找到一个决策点 (j) 使得截距最小,根据 (k=2*s[i]) 我们可以发现这个斜率是单调递增的,那么我们维护的是一个下凸包,不多赘述。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef double D;
    const int N = 50050;
    ll f[N], s[N], sum[N], n, L;
    ll q[N], h, t;
    D X(ll i){ return (D)s[i] + (D)L; }
    D Y(ll i){ return (D)f[i] + (D)X(i) * (D)X(i); }
    D slope(ll i, ll j){ return ( Y(i) - Y(j) ) / ( X(i) - X(j) ); }
    int main(){
        cin >> n >> L; L ++;
        for(ll i=1; i<=n; i++) cin >> sum[i], sum[i] += sum[i-1], s[i] = sum[i] + i;
        h = 1, t = 1;
        for(ll i=1; i<=n; i++){
            while(h < t && slope(q[h], q[h+1]) <= 2 * s[i]) h ++;
            f[i] = f[q[h]] + (s[i] - s[q[h]] - L) * (s[i] - s[q[h]] - L);
            while(h < t && slope(q[t], q[t-1]) >= slope(q[t], i)) t --;
            q[++t] = i;
        }
        cout << f[n];
        return 0;
    }
    
    

    总结

    斜率优化中某些无关量可以在计算斜率的时候消去,所以不用管。

    注意当前不变量和变量之间的关系。

    注意变量类型。

  • 相关阅读:
    最受欢迎的北大通选课导读·1[精品]
    社会保险,
    养老金的计算,
    毫秒 后的一个计算,
    返回格式 的数据结构再次改造,
    阶段状态池子,
    生活,-摘
    融合,
    tableview 也可以实现这个效果,
    字体大小 一致起来,
  • 原文地址:https://www.cnblogs.com/alecli/p/10074063.html
Copyright © 2011-2022 走看看