Loading

笔记-[ZJOI2007]仓库建设

笔记-[ZJOI2007]仓库建设

[ZJOI2007]仓库建设


\(f_i\) 到第 \(i\) 个工厂并且建设了仓库。

\[\begin{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}^i\left(p_hx_i-p_hx_h\right)\}+c_i\\ \end{split} \]

\(s_i=\sum_{h=1}^i p_h\)\(S_i=\sum_{h=1}^i p_hx_h\)

\[\begin{split} f_i=&\min\{f_j+\sum_{h=j+1}^i\left(p_hx_i-p_hx_h\right)\}+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\) 更优:

\[\begin{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\n",DP());
	return 0;
}

\[\Huge\color{#ddd}{\texttt{---END---}} \]

posted @ 2020-03-29 15:25  George1123  阅读(131)  评论(0编辑  收藏  举报