首页 > 其他 > 详细

[HNOI2008]玩具装箱TOY

时间:2018-12-05 23:15:08      阅读:201      评论:0      收藏:0      [点我收藏+]

题意

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;
}

总结

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

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

注意变量类型。

[HNOI2008]玩具装箱TOY

原文:https://www.cnblogs.com/alecli/p/10074063.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!