BZOJ3437 小P的牧场 斜率优化
2017-05-28 08:14
274 查看
BZOJ3437 小P的牧场 斜率优化
Description
要求将一n(n<=1000000)个点的序列分割,每个分割点上有一个代价a[i],每个点被其右边的点控制,代价为其权值b[i]乘以这个点到其右边第一个分割点中间的点的个数,,求出怎么分割代价最小。题解
我们记sum[i]为后缀和,记cnt[j]=∑i=nj(n+1−i)∗b[i]可以得到状态转移方程
f[i]=max(f[j]+cnt[j+1]−(n+1−i)∗(sum[j+1]))
可以用斜率优化,将式子变形得到斜率式,若k<j<i,且j比k优
f[j]−f[k]+cnt[i+1]−cnt[k+1]<(n+1−i)∗(sum[j+1]−sum[k+1])
这里注意一点,因为sum[]为后缀和,所以sum[j+1]-sum[k+1]是一个负数,所以这个不等号要变号。
#include <stdio.h> #include <cmath> #include <cstring> #include <iostream> #include <algorithm> #define MAXN 1000000+10 #define LL long long using namespace std; LL b[MAXN],a[MAXN],l,sum[MAXN],cnt[MAXN],f[MAXN]; int n,q[MAXN],h,t; LL up(int j,int k) {return f[j]-f[k]+cnt[j+1]-cnt[k+1];} LL down(int j,int k) {return sum[j+1]-sum[k+1];} int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); for(int i=1;i<=n;i++) scanf("%lld",&b[i]); for(int i=n;i>=1;i--) { cnt[i]=cnt[i+1]+b[i]*(n+1-i); sum[i]=sum[i+1]+b[i]; } memset(f,62,sizeof(f)); f[0]=0;q[1]=0;h=1;t=2; for(int i=1;i<=n;i++) { while(h<t-1&&up(q[h+1],q[h])<(n+1-i)*down(q[h+1],q[h])) h++; f[i]=f[q[h]]+a[i]+cnt[q[h]+1]-cnt[i]-(n+1-i)*(sum[q[h]+1]-sum[i]); while(h<t-1&&up(q[t-1],q[t-2])/(1.0*down(q[t-1],q[t-2]))<up(i,q[t-2])/(1.0*down(i,q[t-2])))t--; q[t++]=i; } printf("%lld\n",f ); return 0; }
相关文章推荐
- 【bzoj3437】小P的牧场 斜率优化dp
- BZOJ 3437: 小P的牧场 斜率优化DP
- [bzoj3437][dp+斜率优化]小P的牧场
- [BZOJ3437]小P的牧场(斜率优化dp)
- 【bzoj3437】【小p的牧场】【斜率优化dp】
- 【bzoj3437】小P的牧场(斜率优化dp)
- BZOJ 3437: 小P的牧场 斜率优化dp
- 【斜率优化】[BZOJ3437] 小P的牧场
- bzoj 3437: 小P的牧场 -- 斜率优化
- BZOJ 3437 小P的牧场 斜率优化DP
- 【动态规划24】bzoj3437小P的牧场(dp+斜率优化)
- bzoj 3437: 小P的牧场(斜率优化DP)
- [BZOJ 3437]小P的牧场:DP斜率优化
- [BZOJ3437] 小P的牧场 && 斜率优化
- BZOJ3437 小P的牧场 【斜率优化dp】
- BZOJ3437 小P的牧场 【斜率优化dp】
- 【BZOJ3437】小P的牧场,斜率优化DP
- bzoj 3437: 小P的牧场【斜率优化】
- bzoj3437小P的牧场(斜率优化)
- 【BZOJ3437】小P的牧场 斜率优化