bzoj1911[Apio2010]特别行动队 斜率优化dp
1911: [Apio2010]特别行动队
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 5057 Solved: 2492
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
-1 10 -20
2 2 3 4
Sample Output
HINT
dp[i]=dp[j]+a*x*x+b*x+c
x=sum[i]-sum[j]
证明单调性
假设对于i点 k<j且j的决策比k优
dp[j]+a*(sum[i]-sum[j])*(sum[i]-sum[j])+b*(sum[i]-sum[j])+c>=dp[k]+a*(sum[i]-sum[k])*(sum[i]-sum[k])+b*(sum[i]-sum[k])+c
化简得 dp[j]+a*sum[j]*sum[j]-2*a*sum[i]*sum[j]-b*sum[j]>=dp[k]+a*sum[k]*sum[k]-2*a*sum[i]*sum[k]-b*sum[k]
要证明单调性 需证明下面的式子
dp[j]+a*(sum[t]-sum[j])*(sum[t]-sum[j])+b*(sum[t]-sum[j])+c>=dp[k]+a*(sum[t]-sum[k])*(sum[t]-sum[k])+b*(sum[t]-sum[k])+c
化简得dp[j]+a*sum[j]*sum[j]-2*a*sum[t]*sum[j]-b*sum[j]>=dp[k]+a*sum[k]*sum[k]-2*a*sum[t]*sum[k]-b*sum[k]
设t>i 显然sum[t]>=sum[i] 设sum[t]=sum[i]+v
代入sum[t]得 dp[j]+a*sum[j]*sum[j]-2*a*sum[i]*sum[j]-b*sum[j]+v*sum[j]>=dp[k]+a*sum[k]*sum[k]-2*a*sum[i]*sum[k]-b*sum[k]+v*sum[k]
因为j>k 所以sum[j]>=k 上式成立,决策单调性得证
证毕
可以写出斜率式
dp[j]+a*sum[j]^2-2*a*sum[i]*sum[j]-b*sum[j]>=dp[k]+a*sum[k]^2-2*a*sum[i]*sum[k]-b*sum[k] 且j>k
=> dp[j]-dp[k]+a*sum[j]^2-a*sum[k]^2+b*sum[k]-b*sum[j]>=sum[i]*2*a*(sum[j]-sum[k])
=> (dp[j]-dp[k]+a*sum[j]^2-a*sum[k]^2+b*sum[k]-b*sum[j])/(2*a*(sum[j]-sum[k]))>=sum[i]
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<queue> 5 #include<cmath> 6 #include<vector> 7 #include<cstdlib> 8 #include<iostream> 9 #define ll long long 10 #define inf 2147483647 11 #define N 1000005 12 using namespace std; 13 ll dp[N],sum[N]; 14 int a,b,c,q[N]; 15 ll pw(ll x){return x*x;}ll S(int j,int k){return 2*a*(sum[j]-sum[k]);} 16 ll G(int j,int k){return dp[j]-dp[k]+a*pw(sum[j])-a*pw(sum[k])+b*sum[k]-b*sum[j];} 17 double slope(int j,int k){return (double)G(j,k)/S(j,k);} 18 19 int main(){ 20 int n; 21 scanf("%d",&n); 22 scanf("%d%d%d",&a,&b,&c); 23 for(int i=1;i<=n;i++){ 24 int x; 25 scanf("%d",&x); 26 sum[i]=sum[i-1]+x; 27 } 28 int h=1,t=2; 29 for(int i=1;i<=n;i++){ 30 while(h+1<t&&slope(q[h],q[h+1])<=sum[i])h++; 31 int j=q[h],x=sum[i]-sum[j]; 32 dp[i]=dp[j]+a*pw(x)+b*x+c; 33 while(h+1<t&&slope(i,q[t-1])<=slope(q[t-1],q[t-2]))t--; 34 q[t++]=i; 35 } 36 printf("%lld",dp[n]); 37 return 0; 38 }
If you live in the echo,
your heart never beats as loud.
如果你生活在回声里,
你的心跳声永远不会轰鸣作响。