P2120 [ZJOI2007]仓库建设
怎么说呢?算是很水的题了吧...
只要不要一开始就把dp想错就行...
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=1e6+10; const ll INF=2e18; ll n,f[N],x[N],p[N],c[N],q[N],l,r,sum[N],sump[N];//f[i][0/1]表示i及之后的工厂产品 inline int read()//i工厂建仓库的最小代价 { int x=0,ff=1; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*ff; } inline double X(int i) {return sump[i];} inline double Y(int i) {return f[i]+sum[i];} inline double xie(int i,int j) {return (Y(i)-Y(j))/(X(i)-X(j));} int main() { // freopen("1.in","r",stdin); n=read(); for(int i=1;i<=n;++i) x[i]=read(),p[i]=read(),c[i]=read(); for(int i=1;i<=n;++i) sum[i]=sum[i-1]+x[i]*p[i],sump[i]=sump[i-1]+p[i]; for(int i=1;i<=n;++i) f[i]=INF; f[0]=0; for(int i=1;i<=n;++i) { while(l<r&&xie(q[l],q[l+1])<=x[i]) ++l; int j=q[l]; f[i]=f[j]+(sump[i-1]-sump[j])*x[i]-(sum[i-1]-sum[j])+c[i]; while(l<r&&xie(i,q[r])<=xie(q[r],q[r-1])) --r; q[++r]=i; //for(int j=0;j<i;++j) f[i]=min(f[i],f[j]+(sump[i-1]-sump[j])*x[i]-(sum[i-1]-sum[j])); //f[i]+=c[i]; } printf("%lld",f[n]); return 0; }