ZJOI2007仓库建设
斜率优化
而且完美的双单调
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1000010 4 #define rep(a,b,c) for(register int (a)=(b);(a)<=(c);++(a)) 5 #define RG register 6 #define IL inline 7 #define mst(a,b) memset((a),(b),sizeof((a))) 8 #define PN printf("\n") 9 #define PD(a) printf(" %d ",(a)) 10 IL int isitdigit(char c){ return c<='9'&&c>='0'; } 11 IL int read() 12 { 13 RG int s;RG char c; 14 while(!isitdigit(c=getchar())); 15 for(s=c-'0';isitdigit(c=getchar());s=(s<<1)+(s<<3)+c-'0'); 16 return s; 17 } 18 int n; 19 long long k[N],c[N],sum[N],sump[N]; 20 long long f[N]; 21 int head=1,tail=0; 22 struct point{ 23 long long x,y; 24 point(long long a=0,long long b=0):x(a),y(b){} 25 IL const point operator - (const point another) 26 const{ return (point){x-another.x,y-another.y}; } 27 }que[N]; 28 IL long long det(const point a,const point b) 29 { return a.x*b.y-a.y*b.x; } 30 IL int judge(const point a,int b) 31 { return a.y<b*a.x; } 32 int main() 33 { 34 //freopen("thu.in","r",stdin); 35 scanf("%d",&n); 36 rep(i,1,n) 37 { 38 k[i]=read(); 39 RG int p=read(); 40 c[i]=read(); 41 sum[i]=sum[i-1]+p,sump[i]=sump[i-1]+k[i]*p; 42 } 43 rep(i,0,n) 44 { 45 while(head<tail&&judge(que[head+1]-que[head],k[i])) head++; 46 f[i]=que[head].y-k[i]*que[head].x+c[i]+k[i]*sum[i]-sump[i]; 47 point now(sum[i],f[i]+sump[i]); 48 while(head<tail&&det(que[tail]-que[tail-1],now-que[tail])<=0) tail --; 49 que[++tail]=now; 50 } 51 printf("%lld",f[n]); 52 return 0; 53 }