笔记-[ZJOI2007]仓库建设
(f_i) 到第 (i) 个工厂并且建设了仓库。
[egin{split}
f_i=&min{f_j+sum_{h=j+1}^ip_h(x_i-x_h)}+c_i\
=&min{f_j+sum_{h=j+1}^ileft(p_hx_i-p_hx_h
ight)}+c_i\
end{split}
]
设 (s_i=sum_{h=1}^i p_h),(S_i=sum_{h=1}^i p_hx_h)。
[egin{split}
f_i=&min{f_j+sum_{h=j+1}^ileft(p_hx_i-p_hx_h
ight)}+c_i\
=&min{f_j+x_i(s_i-s_j)-(S_i-S_j)}+c_i\
=&min{f_j-x_is_j+S_j}+x_is_i-S_i+c_i\
end{split}
]
考虑 (j=k) 比 (j=t) 更优:
[egin{split}
f_k-x_is_k+S_k<& f_t-x_is_t+S_t\
(f_k+S_k)-(f_t+S_t)<& x_is_k-x_is_t\
frac{(f_k+S_k)-(f_t+S_t)}{s_k-s_t}<& x_i\
end{split}
]
搞定。
Code
#include <bits/stdc++.h>
using namespace std;
//Start
#define re register
#define il inline
#define mk make_pair
#define pb push_back
#define db double
#define lng long long
#define fi first
#define se second
const int inf=0x3f3f3f3f;
const lng INF=0x3f3f3f3f3f3f3f3f;
//Data
int n;
vector<int> x,p,c;
vector<lng> s,S,f;
//DP
il db slope(re int k,re int t){
return 1.0*((f[k]+S[k])-(f[t]+S[t]))/(s[k]-s[t]);
}
il int DP(){
re int l=1,r=0; re vector<int> q(n+7); q[++r]=0;
for(re int i=1;i<=n;i++){
while(l<r&&slope(q[l],q[l+1])<=x[i]) l++;
f[i]=f[q[l]]-(lng)x[i]*s[q[l]]+S[q[l]]+(lng)x[i]*s[i]-S[i]+c[i];
while(l<r&&slope(q[r-1],q[r])>=slope(q[r],i)) r--;
q[++r]=i;
}
return f[n];
}
//Main
int main(){
scanf("%d",&n);
x=p=c=vector<int>(n+7);
s=S=f=vector<lng>(n+7);
for(re int i=1;i<=n;i++){
scanf("%d%d%d",&x[i],&p[i],&c[i]);
s[i]=s[i-1]+p[i],S[i]=S[i-1]+(lng)p[i]*x[i];
}
printf("%lld
",DP());
return 0;
}
[Hugecolor{#ddd}{ exttt{---END---}}
]