【解题思路】

  预处理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\n",f[n]),0;
66 }
View Code