【解题思路】
预处理spi=∑pj(j∈[1,i]),si=si-1+(xi-xi-1)*spi-1表示把工厂1~i-1的产品都运到工厂i的花费。于是把工厂j+1~i的产品都运到工厂i的花费为si-sj-spj*(xi-xj)。
于是易得转移方程:f[i]=min{f[j]+s[i]-s[j]-sp[j]*(x[i]-x[j])+c[i]},转移成同1010的形式:((f[j]-s[j]+sp[j]*x[j])-(f[k]-s[k]+sp[k]*x[k]))/(sp[j]-sp[k])<x[i]。
因为较优转移方式为min,所以维护一个下凸壳即可。听说题目并没有保证x升序?(可能是我星际)所以假装要先排下序,复杂度O(nlog2n)。
【参考代码】
1 #include <algorithm> 2 #define range(i,low,high) for(register int i=(low);i<(high);++i) 3 #define dange(i,high,low) for(register int i=(high);i>(low);--i) 4 #define __function__(type) __attribute__((optimize("-O2"))) inline type 5 #define __procedure__ __attribute__((optimize("-O2"))) inline void 6 using namespace std; 7 8 //quick_io { 9 #include <cctype> 10 #include <cstdio> 11 12 __function__(long long) getint() 13 { 14 char c=getchar(); for(;!isdigit(c)&&c!='-';c=getchar()); 15 short s=1; for(;c=='-';c=getchar()) s*=-1; long long r=0; 16 for(;isdigit(c);c=getchar()) r=(r<<3)+(r<<1)+c-'0'; return r*s; 17 } 18 //} quick_io 19 20 struct node 21 { 22 long long x,p,c; 23 __procedure__ input() {x=getint(),p=getint(),c=getint();} 24 __function__(bool) operator<(const node&t)const{return x<t.x;} 25 }factory[1000010]; 26 27 int q[1000010]; long long s[1000010]={0},sp[1000010]={0},f[1000010]; 28 29 __function__(long long) getDP(const int&i,const int&j) 30 { 31 return f[j]+s[i]-s[j]-sp[j]*(factory[i].x-factory[j].x)+factory[i].c; 32 } 33 __function__(long long) getUP(const int&j,const int&k) 34 { 35 return f[j]-f[k]-s[j]+s[k]+sp[j]*factory[j].x-sp[k]*factory[k].x; 36 } 37 __function__(long long) getDOWN(const int&j,const int&k) 38 { 39 return sp[j]-sp[k]; 40 } 41 42 int main() 43 { 44 int n=getint(); range(i,1,n+1) factory[i].input(); 45 range(i,1,n+1) 46 { 47 s[i]=s[i-1]+(factory[i].x-factory[i-1].x)*sp[i-1]; 48 sp[i]=sp[i-1]+factory[i].p; 49 } 50 int head=0,tail=1; sort(factory+1,factory+n+1),f[0]=0; 51 range(i,1,n+1) 52 { 53 for(;head+1<tail&& 54 getUP(q[head+1],q[head])<factory[i].x*getDOWN(q[head+1],q[head]); 55 ++head 56 ); 57 f[i]=getDP(i,q[head]); 58 for(;head+1<tail&& 59 getUP(i,q[tail-1])*getDOWN(q[tail-1],q[tail-2])< 60 getUP(q[tail-1],q[tail-2])*getDOWN(i,q[tail-1]); 61 --tail 62 ); 63 q[tail++]=i; 64 } 65 return printf("%lld ",f[n]),0; 66 }