bzoj1096: [ZJOI2007]仓库建设

O(n^2)的dp:

f[i]表示i~n的费用

f[i] = min(f[j+1] + c[j] + (i<=k<=j) ((x[j]-x[k])*p[k])) (i+1<=j<=n)

s[i]表示p[i]的前缀和，s2[i]表示x[i]*p[i]的前缀和

f[i] = min(-x[j] * s[i-1] + f[j+1]+c[j]+x[j]*s[j]-s2[j]) + s2[i-1]

s[i-1]随i单调

#include <cstdio>
#define MAXN 1000003
int n;
long long x[MAXN], p[MAXN], c[MAXN];
long long s[MAXN], s2[MAXN], f[MAXN];
struct qtype
{
long long k, b;
} q[MAXN];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%lld%lld%lld", &x[i], &p[i], &c[i]);
s[0] = 0;
for (int i = 1; i <= n; ++i)
s[i] = s[i - 1] + p[i];
s2[0] = 0;
for (int i = 1; i <= n; ++i)
s2[i] = s2[i - 1] + x[i] * p[i];
f[n + 1] = 0;
for (int i = n; i >= 1; --i)
{
long long k, b;
k = -x[i];
b = f[i + 1] + x[i] * s[i] - s2[i] + c[i];
while (tail - head >= 2)
{
double x, y;
x = (q[tail - 2].b - q[tail - 1].b) / (q[tail - 1].k - q[tail - 2].k);
y = q[tail - 1].k * x + q[tail - 1].b;
if (y >= k * x + b)
--tail;
else
break;
}
q[tail].k = k, q[tail].b = b;
++tail;
while (tail - head >= 2)
else
break;
f[i] = q[head].k * s[i - 1] + q[head].b + s2[i - 1];
}
printf("%lld\n", f[1]);
return 0;
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120