Loading

笔记-[SDOI2012]任务安排

笔记-[SDOI2012]任务安排

[SDOI2012]任务安排


\(f_i\) 表示分配到第 \(i\) 个任务的最小费用。

\(st_i=\sum_{h=1}^iT_h\)\(sc_i=\sum_{h=1}^iC_h\)

\[\begin{split} f_i=&\min\{f_j+st_i(sc_i-sc_j)+s(sc_n-sc_j)\}\\ f_i=&f_j+st_isc_i-st_isc_j+s\cdot sc_n-s\cdot sc_j\\ f_j-s\cdot sc_j=&st_isc_j+f_i-st_isc_i-s\cdot sc_n\\ \end{split} \\ \therefore \begin{cases} y=f_j-s\cdot sc_j\\ k=st_i\\ x=sc_j\\ b=f_i-st_isc_i-s\cdot sc_n\\ \end{cases} \\ \Large y=kx+b \]


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,s;
vector<lng> st,sc,f;

//DP
int l,r;
vector<int> q;
il lng X(re int j){return sc[j];}
il lng Y(re int j){return f[j]-sc[j]*s;}
il int Find(re int L,re int R,re lng x){
	while(L<R){
		re int mid=(L+R)>>1;
		if(Y(q[mid+1])-Y(q[mid])>=x*(X(q[mid+1])-X(q[mid]))) R=mid;
		else L=mid+1;
	}
	return q[R];
}
il lng DP(){
	l=1,r=0,q=vector<int>(n+7),q[++r]=0,f=vector<lng>(n+7);
	for(re int i=1;i<=n;i++){
		re int j=Find(l,r,st[i]);
		f[i]=f[j]+st[i]*(sc[i]-sc[j])+(sc[n]-sc[j])*s;
		while(l<r&&(Y(q[r-1])-Y(q[r]))*(X(q[r])-X(i))
		>=(Y(q[r])-Y(i))*(X(q[r-1])-X(q[r]))) r--; q[++r]=i;
	}
	return f[n];
}

//Main
int main(){
	scanf("%d%d",&n,&s),st.pb(0),sc.pb(0);
	for(re int i=1,t,c;i<=n;i++) scanf("%d%d",&t,&c),st.pb(st[i-1]+t),sc.pb(sc[i-1]+c);
	printf("%lld\n",DP());
	return 0;
}

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

posted @ 2020-03-30 19:40  George1123  阅读(101)  评论(0编辑  收藏  举报