bzoj 1096: [ZJOI2007]仓库建设
和刚做的一样,写出一个f[i]分别从f[j],f[k](i>j>k)的方程,然后令f[j]<f[k],得到的是一个f[j]-f[k]<cost(i,k)-cost(i,j),然后可以发现每个点到i的价值可以用x[i]*p[j]-x[j]*p[j]的到,那么都写出来,提一下x[i],就可以把p[j],和p[j]*x[j]搞一个前缀和来维护啦。
(这些题还是都开了LL靠谱。。)
1 #include <bits/stdc++.h> 2 #define LL long long 3 #define lowbit(x) x&(-x) 4 #define inf 0x3f3f3f3f 5 #define eps 1e-5 6 #define N 1000005 7 using namespace std; 8 inline int ra() 9 { 10 int x=0,f=1; char ch=getchar(); 11 while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} 12 while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 13 return x*f; 14 } 15 LL f[N],cst[N],a[N]; 16 int x[N],p[N],c[N],q[N]; 17 int n; 18 double slope(int j, int k) 19 { 20 return (double)(f[j]-f[k]+(a[j]-a[k]))/(double)(cst[j]-cst[k]); 21 } 22 int main(int argc, char const *argv[]) 23 { 24 n=ra(); 25 for (int i=1; i<=n; i++) x[i]=ra(),p[i]=ra(),c[i]=ra(); 26 for (int i=1; i<=n; i++) cst[i]=p[i]+cst[i-1]; 27 for (int i=1; i<=n; i++) a[i]=a[i-1]+p[i]*x[i]; 28 int l=0,r=0; 29 for (int i=1; i<=n; i++) 30 { 31 while (l<r && slope(q[l+1],q[l])<x[i]) l++; 32 int t=q[l]; 33 f[i]=f[t]+c[i]+x[i]*(cst[i]-cst[t])-(a[i]-a[t]); 34 while (l<r && slope(i,q[r])<slope(q[r],q[r-1])) r--; 35 q[++r]=i; 36 } 37 cout<<f[n]; 38 return 0; 39 }