码迷,mamicode.com
首页 > Windows程序 > 详细

【BZOJ1911】[Apio2010]特别行动队 斜率优化DP

时间:2016-04-23 18:00:02      阅读:255      评论:0      收藏:0      [点我收藏+]

标签:

  想了好久啊.。。。

  用了我感觉比较好写的一种(因为没写过维护凸包),另一种是维护凸包的做法,本质一样?推荐http://www.mamicode.com/info-detail-345781.html

  网上的大多数解法:

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

  显然复杂度不对。

  那么假设j>k且f[j]优于f[k]

  f[j]-f[k]+a*(sum[j]^2-sum[k]^2)-b*(sum[j]-sum[k])>2*a*(sum[x]-sum[y])*sum[i] (过程省略,把已知的sum[i]放在一边,剩下的放在一边)

  其实不太明白这个式子求的是啥,但是可以感受到其中的单调之力,我理解为“优度”,优度>sum[i]时就是表示j>k且f[j]优于f[k]的时候,也就是用单调队列维护这个“优度”。(以上为强行YY出的解释

  于是就这样了。。。注意:a<0,除过来要变号(mdzz

  

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #define N 1000000+100
 4 #define ll long long  
 5 using namespace std;
 6 ll sum[N],f[N];
 7 int l,r,n,a,b,c,x;
 8 int q[N];
 9 inline int read()
10 {
11     int ans=0,f=1;
12     char c;
13     while (!isdigit(c=getchar())) if (c==-) f=-1;
14     ans=c-0;
15     while (isdigit(c=getchar())) ans=ans*10+c-0;
16     return ans*f;
17 }
18 inline ll Pow(ll x) {return x*x;}
19 inline double Getk(int x,int y) {return (double)(f[x]-f[y]+a*(Pow(sum[x])-Pow(sum[y]))-b*(sum[x]-sum[y]))/(double)(2*a*(sum[x]-sum[y]));}
20 int main()
21 {
22     n=read();
23     a=read(); b=read(); c=read();
24     for (int i=1;i<=n;i++) x=read(),sum[i]=sum[i-1]+x;
25     for (int i=1;i<=n;i++)
26     {
27         while (l<r && Getk(q[l+1],q[l])<sum[i]) l++;
28         int p=q[l];
29         f[i]=f[p]+a*Pow((sum[i]-sum[p]))+b*(sum[i]-sum[p])+c;
30         while (l<r && Getk(i,q[r])<Getk(q[r],q[r-1])) r--;
31         q[++r]=i;
32     }
33     printf("%lld",f[n]);
34     return 0;
35 }
View Code

 

【BZOJ1911】[Apio2010]特别行动队 斜率优化DP

标签:

原文地址:http://www.cnblogs.com/DMoon/p/5424953.html

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