【洛谷 P3628】 [APIO2010]特别行动队 (斜率优化)

题目链接
斜率优化总结待补,请催更。不催更不补

\[f[i]=f[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum[j])+c \]

\[=f[j]+a*sum[i]^2+a*sum[j]^2-2a*sum[i]*sum[j]+b*sum[i]-b*sum[j]+c \]

\[f[j]+a*sum[j]^2-b*sum[j]+c=2a*sum[i]*sum[j]+f[i]-a*sum[i]^2-b*sum[i] \]

#include <cstdio>
#include <cstring>
#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;
}
inline ll max(ll a, ll b){
	return a > b ? a : b;
}
int a, b, c, n, head, tail;
int sum[MAXN], q[MAXN];
ll f[MAXN];
double k(int i, int j){
	return (double)((ll)f[j] + (ll)a * sum[j] * sum[j] - (ll)b * sum[j] - f[i] - (ll)a * sum[i] * sum[i] + (ll)b * sum[i]) / (sum[j] - sum[i]);
}
int main(){
	memset(f, 128, sizeof f); f[0] = 0;
	n = read(); a = read(); b = read(); c = read();
	for(int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + read();
	for(int i = 1; i <= n; ++i){
	   while(head < tail && k(q[head], q[head + 1]) > 2 * a * sum[i]) ++head;
	   int j = q[head];
	   f[i] = f[j] + (ll)a * sum[j] * sum[j] - (ll)b * sum[j] + c - 2ll * a * sum[i] * sum[j] + (ll)a * sum[i] * sum[i] + (ll)b * sum[i];
	   while(head < tail && k(q[tail], i) >= k(q[tail - 1], q[tail])) --tail;
	   q[++tail] = i;
	}
	printf("%lld\n", f[n]);
	return 0;
}
posted @ 2019-01-26 14:19  Qihoo360  阅读(157)  评论(0编辑  收藏  举报
You're powerful!