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

  想了好久啊.。。。

  用了我感觉比较好写的一种(因为没写过维护凸包),另一种是维护凸包的做法,本质一样?推荐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 }



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

时间: 2024-11-09 05:08:57

【BZOJ1911】[Apio2010]特别行动队 斜率优化DP的相关文章

bzoj1911[Apio2010]特别行动队 斜率优化dp

1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 5057  Solved: 2492[Submit][Status][Discuss] Description Input Output Sample Input 4 -1 10 -20 2 2 3 4 Sample Output 9 HINT dp[i]=dp[j]+a*x*x+b*x+cx=sum[i]-sum[j] 证明单调性假设对于i点 k<j且j的决策

[APIO2010]特别行动队 --- 斜率优化DP

[APIO2010]特别行动队 题面很直白,就不放了. 太套路了,做起来没点感觉了. \(dp(i)=dp(j)+a*(s(i)-s(j))^{2}+b*(s(i)-s(j))+c\) 直接推出一个斜率优化的式子上单调队列就好了 时间/空间复杂度:\(O(n)\) #include<cstdio> #define sid 1000500 #define ri register int #define ll long long #define dd double using namespace

BZOJ 1911: [Apio2010]特别行动队 [斜率优化DP]

1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 4142  Solved: 1964[Submit][Status][Discuss] Description Input Output Sample Input 4 -1 10 -20 2 2 3 4 Sample Output 9 HINT f[i]=max{f[j]+...} 随便一化就好了 (a*(s[k]*s[k]-s[j]*s[j])+f[k]-f[

APIO2010 特别行动队 &amp; 斜率优化DP入门讲解

做完此题之后 自己应该算是真正理解了斜率优化DP 根据状态转移方程f[i]=max(f[j]+ax^2+bx+c),x=sum[i]-sum[j] 可以变形为 f[i]=max((a*sum[j]^2-b*sum[j])-(2a*sum[j]*sum[i]))+(a*sum[i]^2+b*sum[i]+c) 我们可以把每个决策映射到平面上的一个点 其中x坐标为(a*sum[j]^2-b*sum[j])代表此决策的固定价值(与转移到哪无关) y坐标为-(2a*sum[j]) 代表此决策的潜在价值(

BZOJ 1911 特别行动队(斜率优化DP)

应该可以看出这是个很normal的斜率优化式子.推出公式搞一搞即可. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set>

APIO 2010 特别行动队 | 斜率优化DP

luogu 3628 si表示序列的前缀和f(i)表示将序列的前i个划分若干段的最大价值f(i)= max{f(j)+a∗(si−sj)2+b∗(si−sj)+c},1≤j<i    = max{−2a*sj*si+f(j)+a*sj*sj−b*sj}+a*si*si+b*si+c,1≤j<i 1 #include <cstdio> 2 #include <string> 3 4 typedef long long ll; 5 6 ll a, b, c; 7 8 ll

BZOJ1911 [Apio2010]特别行动队 - 动态规划 - 斜率优化

欢迎访问~原文出处--博客园-zhouzhendong&AK 去博客园看该题解 题目传送门 题意概括 把一个整数序列划分成任意连续的段,使得划分出来的每一段的价值和最大. 对于某一段,价值的计算公式为 V=ax^2+bx+c,其中 x 为当前段的数值和. 题解 这题是博主大蒟蒻的第一道斜率优化DP题-- C++:while (1) 懵逼++; Pascal:while (true) do inc(懵逼); 本题首先一看就是 DP 题. 但是一看 1<=n<=1000000,-5<

Bzoj1911 [Apio2010]特别行动队

1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3969  Solved: 1873 Description Input Output Sample Input 4 -1 10 -20 2 2 3 4 Sample Output 9 HINT Source 斜率优化DP f[分组末尾]=最优解 f[i] = max{f[j]+A(s[i]-s[j])^2+B(s[i]-s[j])+C}  (0<=j<i)

bzoj1911 [Apio2010]特别行动队commando

题目链接 斜率优化 1 #include<cstdio> 2 #include<cstdlib> 3 #include<string> 4 #include<cstring> 5 #include<cmath> 6 #define re(i,l,r) for(int i=(l);i<=(r);i++) 7 using namespace std; 8 typedef long long LL; 9 template<typename