笔记-[SDOI2012]任务安排
(f_i) 表示分配到第 (i) 个任务的最小费用。
令 (st_i=sum_{h=1}^iT_h),(sc_i=sum_{h=1}^iC_h)。
[egin{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+scdot sc_n-scdot sc_j\
f_j-scdot sc_j=&st_isc_j+f_i-st_isc_i-scdot sc_n\
end{split}
\
herefore
egin{cases}
y=f_j-scdot sc_j\
k=st_i\
x=sc_j\
b=f_i-st_isc_i-scdot 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
",DP());
return 0;
}
[Hugecolor{#ddd}{ exttt{---END---}}
]