【洛谷 P2120】 [ZJOI2007]仓库建设(斜率优化)

题目链接
斜率优化+1,好吧不水分了。
玩具装箱那题以后再做,当作复习吧。
(f[i]=f[j]-(sum[i]-sum[j])*dis[i]+p[i])
(f[j]=-dis[i]*sum[j]+sum[i]*dis[i]+f[i]-p[i])

#include <cstdio>
#include <algorithm>
using namespace std;
#define ll long long
const int MAXN = 1000010;
inline int read(){
    int s = 0, w = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); }
    return s * w;
}
int p[MAXN], sum[MAXN], dis[MAXN], q[MAXN], c[MAXN];
int n, head, tail;
ll ans = 2147483647;
ll f[MAXN];
inline double k(int i, int j){
	return (double)(f[i] - f[j]) / (sum[i] - sum[j]);
}
int main(){
	n = read();
	for(int i = 1; i <= n; ++i){
	   dis[i] = read();
	   sum[i] = sum[i - 1] + (c[i] = read());
	   p[i] = read();
    }
    f[0] = p[n];
    for(int i = 1; i <= n; ++i){
       dis[i] = dis[n] - dis[i];
       f[0] += (ll)dis[i] * c[i];
    }
    ans = f[0];
    for(int i = 1; i < n; ++i){
       while(head < tail && k(q[head], q[head + 1]) < -dis[i]) ++head;
       int j = q[head];
       f[i] = f[j] - (ll)(sum[i] - sum[j]) * dis[i] + p[i];
       ans = min(ans, f[i]);
       while(head < tail && k(q[tail - 1], q[tail]) >= k(q[tail], i)) --tail;
       q[++tail] = i;
    }
    printf("%lld
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Qihoo360/p/10329587.html