bzoj 1911 [Apio2010]特别行动队(斜率优化+DP)

1911: [Apio2010]特别行动队

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 3191  Solved: 1450
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

4
-1 10 -20
2 2 3 4

Sample Output

9

HINT

Source

【思路】

斜率优化。

设f[i]表示将前i个分组的最优值,则有转移方程式:

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

经过化简得到:

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

单调队列维护上凸包即可。

【代码】

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4
 5 typedef long long LL;
 6 const int N = 1000000+10;
 7 struct point { LL x,y;
 8 }q[N],now;
 9 int n,a,b,c,L,R;  LL C[N];
10
11 LL cross(point a,point b,point c) {
12     return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
13 }
14 void read(LL& x) {
15     char c=getchar(); while(!isdigit(c)) c=getchar();
16     x=0; while(isdigit(c)) x=x*10+c-‘0‘ , c=getchar();
17 }
18 int main() {
19     scanf("%d%d%d%d",&n,&a,&b,&c);
20     for(int i=1;i<=n;i++)
21         read(C[i]) , C[i]+=C[i-1];
22     for(int i=1;i<=n;i++) {
23         while(L<R && q[L].y-2*a*C[i]*q[L].x <= q[L+1].y-2*a*C[i]*q[L+1].x) L++;
24         now.x=C[i];
25         now.y=q[L].y-2*a*C[i]*q[L].x+2*a*C[i]*C[i]+c;
26         while(L<R && cross(q[R-1],now,q[R])<=0) R--;
27         q[++R]=now;
28     }
29     printf("%lld",q[R].y+b*C[n]-a*C[n]*C[n]);
30     return 0;
31 }
时间: 2024-10-24 20:35:49

bzoj 1911 [Apio2010]特别行动队(斜率优化+DP)的相关文章

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[

【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*

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

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]) 代表此决策的潜在价值(

斜率优化专题4——bzoj 1911: [Apio2010] 特别行动队 题解

[原题] 1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 2134  Solved: 911 [Submit][Status] Description Input Output Sample Input 4 -1 10 -20 2 2 3 4 Sample Output 9 HINT [分析]只要跟着我前面的题目走,这道题真的是太水了.神马题解都不用参考,公式随便推. 易知方程是f[i]=max(f[j]+

BZOJ 1911: [Apio2010]特别行动队( dp + 斜率优化 )

sum为战斗力的前缀和 dp(x) = max( dp(p)+A*(sumx-sump)2+B*(sumx-sump)+C )(0≤p<x) 然后斜率优化...懒得写下去了... -------------------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; typedef long long ll; const in

bzoj 1911: [Apio2010]特别行动队

1 #include<cstdio> 2 #include<iostream> 3 #define M 1000009 4 #define ll long long 5 using namespace std; 6 int n,zhan[M],h,t; 7 ll a,b,c,f[M],sum[M]; 8 double pai(int a1,int a2) 9 { 10 double ss=(f[a1]-f[a2])/(1.0*a*(sum[a2]-sum[a1])); 11 ret

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

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