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 read() {
 9     ll x = 0, f = 1;
10     char c = getchar();
11     while (!isdigit(c)) {
12         if (c == ‘-‘) f = -1;
13         c = getchar();
14     }
15     while (isdigit(c)) {
16         x = (x << 3) + (x << 1) + (c ^ 48);
17         c = getchar();
18     }
19     return x * f;
20 }
21
22 ll s[1000005], f[1000005]; int Q[1000005];
23
24 ll K(int j) {
25     return -2 * a * s[j];
26 }
27
28 ll B(int j) {
29     return f[j] + a * s[j] * s[j] - b * s[j];
30 }
31
32 ll Y(int i, int j) {
33     return K(j) * s[i] + B(j);
34 }
35
36 bool cover(int i, int j, int k) {
37     ll y1 = (K(i) - K(k)) * (B(j) - B(i));
38     ll y2 = (K(i) - K(j)) * (B(k) - B(i));
39     return y1 <= y2;
40 }
41
42 int main() {
43     int n = read(); a = read(), b = read(), c = read();
44     for (int i = 1; i <= n; ++ i) {
45         ll x = read(); s[i] = s[i - 1] + x;
46     }
47     int l = 0, r = 0;
48     for (int i = 1; i <= n; ++ i) {
49         while (l < r && Y(i, Q[l]) <= Y(i, Q[l + 1])) ++ l;
50         f[i] = Y(i, Q[l]) + a * s[i] * s[i] + b * s[i] + c;
51         while (l < r && cover(i, Q[r], Q[r - 1])) -- r;
52         Q[++r] = i;
53     }
54     printf("%lld\n", f[n]);
55 }

原文地址:https://www.cnblogs.com/milky-w/p/8541609.html

时间: 2024-10-09 23:19:34

APIO 2010 特别行动队 | 斜率优化DP的相关文章

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

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

[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

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的决策

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[

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

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

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

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1911 分析: 首先可以的到裸的方程f[i]=max{f[j]+a*(Si-Sj)^2+b*(Si-Sj)+c} 0<j<i 简化一下方程,我们知道对于一次项,最后结果肯定是b*Sn 所以可以写成f[i]=max{f[j]+a*(Si-Sj)^2+c} 0<j<i 我们不妨设0<x<y<i,且x比y优 即f[x]+a*(Si-Sx)^2+c>f[y]+a*

bzoj2149拆迁队 斜率优化dp+分治

2149: 拆迁队 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 397  Solved: 177[Submit][Status][Discuss] Description lanxisi带领着他的拆迁队来整治一个街道.这个街道由N个旧房子组成,从左到右编号为1..N.每个旧房子i有一个正整数的美观度Ai. lanxisi希望整个街道从左到右美观度严格递增,也就是保证Ai<Aj(i<j).但是旧的街道明显不符合这个要求,于是lanxisi希望拆

[APIO 2010] 特别行动队

[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1911 [算法] 设前i个士兵"修正"后的最大战斗力为fi 令sumi表示x的前缀和 显然 , 有状态转移方程 : fi = max{ fj + a * (sumi - sumj) ^ 2 + b * (sumi - sumj) + c } 对该式进行化简 , 得 : fi = max{ fj + asumi ^ 2 + asumj ^ 2 - 2asumisumj + b