码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1911 (特别行动队)

时间:2016-06-02 17:59:09      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:

题意:给定一个数列,将其分成若干段,若某段的和为x则这段的价值为a*x*x+b*x+c。求一种分法使得总价值最大

f[i]为到第i个时的最大价值,

f[i]=max(f[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum[j])+c

若j1<j2且j2更优

f[j1]+a*sum[i]^2+a*sum[j1]^2-2*a*sum[i]*sum[j1]+b*sum[i]-b*sum[j1]+c<f[j2]+a*sum[i]^2+a*sum[j2]^2-2*a*sum[i]*sum[j2]+b*sum[i]-b*sum[j2]+c

最终化简得到

f[j1]-f[j2]+a*sum[j1]^2-a*sum[j2]^2-b*sum[j1]+b*sum[j2]<2*a*sum[i]*(sum[j1]-sum[j2])

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<string>
 6 #include<algorithm>
 7 int n;
 8 long long sum[1000005],a,b,c,x,q[1000005],f[1000005];
 9 long long sqr(long long x){
10     return x*x;
11 }
12 double slope(int k,int j){
13     return double((f[j]-f[k])+a*sqr(sum[j])-a*sqr(sum[k])+b*(sum[k]-sum[j]))/(2*a*(sum[j]-sum[k]));
14 }
15 
16 int main(){
17     scanf("%d",&n);
18     scanf("%lld%lld%lld",&a,&b,&c);
19     sum[0]=0;
20     for (int i=1;i<=n;i++){
21         scanf("%lld",&x);
22         sum[i]=sum[i-1]+x;
23     }
24     int l=0,r=0;
25     for (int i=1;i<=n;i++){
26         while (l<r&&slope(q[l],q[l+1])<sum[i]) l++;
27         int t=q[l];
28         f[i]=f[t]+a*(sum[i]-sum[t])*(sum[i]-sum[t])+b*(sum[i]-sum[t])+c;
29         while (l<r&&slope(q[r-1],q[r])>slope(q[r],i)) r--;
30         q[++r]=i;
31     }
32     printf("%lld",f[n]);
33 }

 

BZOJ 1911 (特别行动队)

标签:

原文地址:http://www.cnblogs.com/qzqzgfy/p/5553634.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!