[luogu3628][bzoj1911][APIO2010]特别行动队【动态规划+斜率优化DP】
题目描述
给你一个数列,让你将这个数列分成若干段,使其每一段的和的\(a \times sum^2 + b \times sum + c\)的总和最大。
分析
算是一道斜率优化的入门题。
首先肯定是考虑\(O(n^2)\)的暴力DP。
定义状态\(f[i]\)表示最后一段的结尾是\(i\)的最大答案。
那么枚举j,得到转移方程为\(f[i]=max(f[i],f[j]+a\times (sum[i]-sum[j])^2+b\times(sum[i]-sum[j])+c\)
注意这里的转移方程不是\(sum[i]-sum[j-1]\)而是\(sum[i]-sum[j]\),因为j是属于前一段的,所以不能算j-1这一个格子。
40分蜜汁错误和全部剩下全部T飞。
#include <bits/stdc++.h>
#define ll long long
#define ms(a, b) memset(a, b, sizeof(a))
#define inf 0x3f3f3f3f
#define N 1000005
using namespace std;
template <typename T>
inline void read(T &x) {
x = 0; T fl = 1;
char ch = 0;
while (ch < '0' || ch > '9') {
if (ch == '-') fl = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
x *= fl;
}
ll sqr(ll x) {
return x * x;
}
int n;
ll a, b, c;
ll x[N], sum[N], f[N];
int main() {
read(n);
read(a); read(b); read(c);
for (int i = 1; i <= n; i ++) {
read(x[i]);
sum[i] = sum[i - 1] + x[i];
}
for (int i = 1; i <= n; i ++)
for (int j = 0; j < i; j ++)
f[i] = max(f[i], f[j] + sqr(sum[i] - sum[j]) * a + (sum[i] - sum[j]) * b + c);
printf("%lld\n", f[n]);
return 0;
}
很显然这不是正解,那么我们就考虑优化DP。
考虑斜率优化。按照斜率优化的标准套路。
假设\(0<=k<j<i\)时,j的状态比k要优。。
那么很明显就得到了以下的式子,再将其化简:
\[f_j+a\times(sum_i-sum_j)^2+b\times(sum_i-sum_j)+c>=f_k+a\times a\times(sum_i-sum_j)^2+b\times(sum[i]-sum[j])+c\]
以下的所有操作都是初中内容。(可能会跳步,但是看得懂)
\[f_j-2asum_isum_j+asum_j^2-bsum_j>=f_k-2asum_isum_k+asum_k^2-bsum_k\]
\[\frac{(f_j+asum_j^2-bsum_j)-(f_k+asum_k^2-bsum_k)}{sum_j-sum_k}>=2sum_i\]
可以发现:左边单调递增,右边单调递减。那么维护斜率上凸包。
#include <bits/stdc++.h>
#define ll long long
#define ms(a, b) memset(a, b, sizeof(a))
#define inf 0x3f3f3f3f
#define N 1000005
#define db double
using namespace std;
template <typename T>
inline void read(T &x) {
x = 0; T fl = 1;
char ch = 0;
while (ch < '0' || ch > '9') {
if (ch == '-') fl = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
x *= fl;
}
ll sqr(ll x) {
return x * x;
}
int n;
ll a, b, c;
ll x[N], sum[N], f[N];
int q[N];
ll get_x(int i) {
return sum[i];
}
ll get_y(int i) {
return f[i] + a * sqr(sum[i]) - b * sum[i];
}
db get_slope(int i, int j) {
return (1.0 * (get_y(j) - get_y(i))) / (1.0 * (get_x(j) - get_x(i)));
}
int main() {
read(n);
read(a); read(b); read(c);
for (int i = 1; i <= n; i ++) {
read(x[i]);
sum[i] = sum[i - 1] + x[i];
}
int h = 0, t = 0;
for (int i = 1; i <= n; i ++) {
while (h < t && get_slope(q[h] , q[h + 1]) >= 2.0 * a * sum[i]) h ++;
int j = q[h];
f[i] = f[j] + a * sqr(sum[i] - sum[j]) + b * (sum[i] - sum[j]) + c;
while (h < t && get_slope(q[t - 1], q[t]) <= get_slope(q[t], i)) t --;
q[++ t] = i;
}
printf("%lld\n", f[n]);
return 0;
}
[luogu3628][bzoj1911][APIO2010]特别行动队【动态规划+斜率优化DP】的更多相关文章
- BZOJ1911 [Apio2010]特别行动队 - 动态规划 - 斜率优化
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 UPD(2018-04-01):用Latex重打了公式…… 题意概括 把一个整数序列划分成任意连续的段,使得划分出 ...
- 2018.09.07 bzoj1911: [Apio2010]特别行动队(斜率优化dp)
传送门 斜率优化dp经典题. 题目中说的很清楚,设f[i]表示前i个数分配出的最大值. 那么有: f[i]=max(f[j]+A∗(sum[i]−sum[j])2+B∗(sum[i]−sum[j])+ ...
- [bzoj1911][Apio2010特别行动队] (动态规划+斜率优化)
Description Input Output Sample Input - - Sample Output HINT Solution 斜率优化动态规划 首先易得出这样的一个朴素状态转移方程 f[ ...
- BZOJ1911 [Apio2010]特别行动队 【斜率优化】
1911: [Apio2010]特别行动队 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 5005 Solved: 2455 [Submit][Sta ...
- bzoj 1911 [Apio2010]特别行动队(斜率优化+DP)
1911: [Apio2010]特别行动队 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 3191 Solved: 1450[Submit][Statu ...
- P3628 [APIO2010]特别行动队(斜率优化dp)
P3628 [APIO2010]特别行动队 设$s[i]$为战斗力前缀和 显然我们可以列出方程 $f[i]=f[j]+a*(s[i]-s[j])^{2}+b*(s[i]-s[j])+c$ $f[i]= ...
- 【BZOJ】1911: [Apio2010]特别行动队(斜率优化dp)
题目 传送门:QWQ 分析 用$ dp[i] $ 表示前 i 个人组成的战斗力之和 然后显然$ dp[i]=Max ( dp[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum ...
- _bzoj1911 [Apio2010]特别行动队【斜率优化dp】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1911 裸的斜率优化dp. #include <cstdio> const int ...
- bzoj 1911: [Apio2010]特别行动队【斜率优化dp】
仔细想想好像没学过斜率优化.. 很容易推出状态转移方程\( f[i]=max{f[j]+a(s[i]-s[j])^2+b(s[i]-s[j])+c} \) 然后考虑j的选取,如果选j优于选k,那么: ...
- 【BZOJ 1191】 [Apio2010]特别行动队 (斜率优化)
dsy1911: [Apio2010]特别行动队 [题目描述] 有n个数,分成连续的若干段,每段的分数为a*x^2+b*x+c(a,b,c是给出的常数),其中x为该段的各个数的和.求如何分才能使得各个 ...
随机推荐
- Django 中的Form、ModelForm
一.ModelForm 源码 class ModelForm(BaseModelForm, metaclass=ModelFormMetaclass): pass def modelform_fact ...
- 【问题解决方案】之 关于某江加密视频swf专用播放器仍无法播放的问题
前言: 从pt上下载了一些语言学习的视频之后一直打不开,百度谷歌了若干种方法仍然无解.无奈放弃. 某日从百度知道里又看到一个方法,试了一下,居然灵了.呜呼哀哉.赶紧记下来. 原方法链接:https:/ ...
- 【学习总结】之 3Blue1Brown系列
刷知乎看到的,各种力荐. YouTube: https://www.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw/featured B站: https:// ...
- HTML,CSS笔记
text-indent 属性规定文本块中首行文本的缩进.允许使用负值.如果使用负值,那么首行会被缩进到左边.p{ text-indent:50px; } HTML <label> 标签的 ...
- Linux 典型应用之WebServer 安装和配置
Apache的基本操作 安装 yum install httpd 启动 service httpd start 在浏览器中输入以下Ip 发现无法访问 http://192.168.1.109/ 输入 ...
- Oracle 表空间的创建与管理
Oracle数据库创建之后有一些默认的表空间随之被创建,查询数据字典 dba_data_files 可以得到数据库当前的所有表空间信息. select * from v$tablespace; sel ...
- MT4下载历史数据
这个网站只能下载2001年-当前时间前一个月的数据,还是挺全的.但是下载下来之后好像是一分钟图的,妈蛋其实我想要1小时图的EURUSD历史数据. 网站地址:http://www.fxfupan.com ...
- java连接CentOS7上的redis
这篇博客写得挺全的: https://blog.csdn.net/achenyuan/article/details/78521831?locationNum=3&fps=1 我也是跟着这篇博 ...
- JS --- 本地保存localStorage、sessionStorage用法总结
JS的本地保存localStorage.sessionStorage用法总结 localStorage.sessionStorage是Html5的特性,IE7以下浏览器不支持 为什么要掌握localS ...
- Java HashMap的put操作(Java1.6)
https://www.cnblogs.com/skywang12345/p/3310835.html // 存储数据的Entry数组,长度是2的幂. // HashMap是采用拉链法实现的,每一个E ...