DP/斜率优化
斜率优化基本题……等等,好像就没啥变化啊= =
嗯目测这题跟仓库建设差不多?写题的时候倒是没想这么多……直接推了公式。
$$f[i]=min\{f[j]+cal(j,i)+a[i]\}$$
哦麻烦的还是这个$cal(j,i)$
我们令$s[i]=\sum_{k=1}^{i}b[k] c[i]=\sum_{k=1}^{i}(b[k]*k)$
则有$cal(j,i)=(s[i]-s[j])*i-(c[i]-c[j])$(问我怎么想到的?这个嘛……像这题这种要求“阶梯形求和”的,基本都是利用矩形和$\sum a[i]*i=s[i]*i$ 以及 阶梯形和 $ \sum (a[i]*i) $两种前缀和加加减减拼凑出来的)
所以有$f[i]=min\{ f[j]+(s[i]-s[j])*i-(c[i]-c[j])+a[i] \}$
单调性证明:$( j > k )$
\[ \begin{aligned} f[j]+(s[i]-s[j])*i-(c[i]-c[j])+a[i] &< f[k]+(s[i]-s[k])*i-(c[i]-c[j])+a[i] \\ f[j]-f[k]+c[j]-c[k] &< i*(s[j]-s[k]) \\ \frac{f[j]-f[k]+c[j]-c[k]}{s[j]-s[k]} &< i \end{aligned} \]
1 /************************************************************** 2 Problem: 3437 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:2096 ms 7 Memory:44240 kb 8 ****************************************************************/ 9 10 //BZOJ 3437 11 #include<cmath> 12 #include<vector> 13 #include<cstdio> 14 #include<cstring> 15 #include<cstdlib> 16 #include<iostream> 17 #include<algorithm> 18 #define rep(i,n) for(int i=0;i<n;++i) 19 #define F(i,j,n) for(int i=j;i<=n;++i) 20 #define D(i,j,n) for(int i=j;i>=n;--i) 21 #define pb push_back 22 using namespace std; 23 int getint(){ 24 int v=0,sign=1; char ch=getchar(); 25 while(ch<‘0‘||ch>‘9‘){ if (ch==‘-‘) sign=-1; ch=getchar();} 26 while(ch>=‘0‘&&ch<=‘9‘){ v=v*10+ch-‘0‘; ch=getchar();} 27 return v*=sign; 28 } 29 const int N=1e6+10; 30 typedef long long LL; 31 /******************tamplate*********************/ 32 LL a[N],b[N],c[N],s[N],f[N]; 33 int q[N],l,r,n; 34 inline double slop(int k,int j){ 35 return double(f[j]-f[k]+c[j]-c[k])/double(s[j]-s[k]); 36 } 37 int main(){ 38 n=getint(); 39 F(i,1,n) a[i]=getint(); 40 F(i,1,n){ 41 b[i]=getint(); 42 s[i]=s[i-1]+b[i]; 43 c[i]=c[i-1]+b[i]*i; 44 } 45 F(i,1,n){ 46 while(l<r && slop(q[l],q[l+1])<i)l++; 47 int t=q[l]; 48 f[i]=f[t]+(s[i]-s[t])*i-c[i]+c[t]+a[i]; 49 while(l<r && slop(q[r-1],q[r])>slop(q[r],i))r--; 50 q[++r]=i; 51 } 52 printf("%lld\n",f[n]); 53 return 0; 54 }
时间: 2024-10-22 09:53:50