BZOJ1911 [Apio2010]特别行动队 - 动态规划 - 斜率优化
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门
UPD(2018-04-01):用Latex重打了公式……
题意概括
把一个整数序列划分成任意连续的段,使得划分出来的每一段的价值和最大。
对于某一段,价值的计算公式为 $V=ax^2+bx+c$,其中 $x$ 为当前段的数值和。
题解
这题是博主大蒟蒻的第一道斜率优化DP题……
C++:while (1) 懵逼++;
Pascal:while (true) do inc(懵逼);
本题首先一看就是 DP 题。
但是一看 $1\leq n\leq 1000000,-5\leq a\leq -1,|b|\leq 10000000,|c|\leq 10000000,1\leq xi\leq 100$
彻底吓懵!
一脸懵逼……
还是一脸懵逼……
突(bai)然(du)发(yi)现(xia)可以用斜率优化。
为了减少代码量,好心的出题人特意规定了$-5\leq a\leq -1$
我们来考虑一下:
用 $dp_i$ 表示划分到前$i$个所能得到的最大价值和。
我们设 $sum_i$ 为前$i$个的前缀和,
那么
$$dp_i=max\{dp_j+a(sum_i-sum_j)^2+b(sum_i-sum_j)+c\} (0\leq j<i)$$
貌似是一个$n^2$的状态转移方程。
其实就是一个$n^2$的状态转移方程。
接下来就是斜率优化了!
我们假设对于$dp_i$来说,从$j$转移比从$k$转移更优秀($j>k$),那么有如下的表达式:
$$dp_j+a(sum_i-sum_j)^2+b(sum_i-sum_j)+c>dp_k+a(sum_i-sum_k)^2+b(sum_i-sum_k)+c$$
so
$$dp_j+a(sum_i-sum_j)^2+b(sum_i-sum_j)>dp_k+a(sum_i-sum_k)^2+b(sum_i-sum_k)$$
$$dp_j+a\cdot sum_i^2-2a\cdot sum_isum_j+a\cdot sum_j^2+b\cdot sum_i-b\cdot sum_j>dp_k+a\cdot sum_i^2-2a\cdot sum_isum_k+a\cdot sum_k^2+b\cdot sum_i-b\cdot sum_k$$
$$dp_j-2a\cdot sum_isum_j+a\cdot sum_j^2-b\cdot sum_j>dp_k-2a\cdot sum_isum_k+a\cdot sum_k^2-b\cdot sum_k$$
$$(dp_j+a\cdot sum_j^2-b\cdot sum_j)- (dp_k+a\cdot sum_k^2-b\cdot sum_k)>2a\cdot sum_i(sum_j-sum_k)$$
so
$$\frac{(dp_j+a\cdot sum_j^2-b\cdot sum_j)-(dp_k+a\cdot sum_k^2-b\cdot sum_k)}{sum_j-sum_k}>2a\cdot sum_i$$
我们设$x_p=sum_p,y_p=dp_p+a\cdot sum_p^2-b\cdot sum_p$,
那么原来的方程可以表示为:
$$\frac{y_j-y_k}{x_j-x_k}>2a\cdot sum_i$$
左边不就是斜率的表达式吗!!
所以叫斜率优化。
当然前面的只是一些化简,关键是接下来的:
我们设$g_{i,j}=\Large\frac{y_i-y_j}{x_i-x_j}$
注意$a$是一个负数,而且$sum_i$是随着$i$的增大而增大的,所以$2a\cdot sum_i$一定是单调递减的!
如果$g_{i,j}>g_{j,k}$那么决策$j$一定是没用的!$(k<j<i)$
分两种情况进行讨论:
1. 如果$g_{i,j}>2a\cdot sum_x$,那么说明决策$i$优于决策$j$,那么$j$就是没用的。就算以后$2a\cdot sum_x$会变,$x$只能变大,所以 $2a\cdot sum_x$也只能变小,所以该表达式仍然满足。
2. 如果$g_{i,j}<2a\cdot sum_x$,那么$g_{j,k}<2a\cdot sum_x$,那么$j$就会比$k$劣,同样也会把$j$扔掉。
然后我们单调队列弄几下就好了。
在$dp$的过程中,按照“如果$g_{i,j}>g_{j,k}$那么决策$j$一定是没用的!”的规则入队,按照 如果$g_{i,j}>2a\cdot sum_x$的规则出队即可。
代码
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
const int N=+;
int n,head,tail;
LL a,b,c,r[N],sum[N],x[N],y[N],dp[N],q[N];
double g(int i,int j){
double xi=x[i],xj=x[j],yi=y[i],yj=y[j];
return (yi-yj)/(xi-xj);
}
int main(){
scanf("%d%lld%lld%lld",&n,&a,&b,&c);
sum[]=;
for (int i=;i<=n;i++)
scanf("%lld",&r[i]),sum[i]=sum[i-]+r[i];
memset(x,,sizeof x);
memset(y,,sizeof y);
head=,tail=;
q[++tail]=;
for (int i=;i<=n;i++){
while (head+<=tail&&g(q[head],q[head+])>*a*sum[i])
head++;
LL s=sum[i]-sum[q[head]];
dp[i]=dp[q[head]]+a*s*s+b*s+c;
x[i]=sum[i],y[i]=dp[i]+a*sum[i]*sum[i]-b*sum[i];
while (head+<=tail&&g(q[tail-],q[tail])<g(q[tail],i))
tail--;
q[++tail]=i;
}
printf("%lld",dp[n]);
return ;
}
BZOJ1911 [Apio2010]特别行动队 - 动态规划 - 斜率优化的更多相关文章
- [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 ...
- 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]特别行动队(dp 斜率优化)
题意 题目链接 Sol 裸的斜率优化,注意推导过程中的符号问题. #include<bits/stdc++.h> #define Pair pair<int, int> #de ...
- 【BZOJ-1911】特别行动队 DP + 斜率优化
1911: [Apio2010]特别行动队 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 3478 Solved: 1586[Submit][Statu ...
- 【BZOJ 1191】 [Apio2010]特别行动队 (斜率优化)
dsy1911: [Apio2010]特别行动队 [题目描述] 有n个数,分成连续的若干段,每段的分数为a*x^2+b*x+c(a,b,c是给出的常数),其中x为该段的各个数的和.求如何分才能使得各个 ...
- bzoj 1911 [Apio2010]特别行动队(斜率优化+DP)
1911: [Apio2010]特别行动队 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 3191 Solved: 1450[Submit][Statu ...
- BZOJ 1911: [Apio2010]特别行动队( dp + 斜率优化 )
sum为战斗力的前缀和 dp(x) = max( dp(p)+A*(sumx-sump)2+B*(sumx-sump)+C )(0≤p<x) 然后斜率优化...懒得写下去了... ------- ...
- 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]= ...
随机推荐
- python bytes/str
http://eli.thegreenplace.net/2012/01/30/the-bytesstr-dichotomy-in-python-3/
- Maven安装与配置及使用
下载及安装 官方下载地址:直达官网下载页面 进入下载页面后,根据你电脑所装jdk版本选择对应版本的maven进行下载. 我们可以看到该页上边红框内写明了,maven3.3版以上支持的是JDK1.7+的 ...
- jquery中的attr与prop的区别,什么时候用attr,什么时候用prop
只要有 Boolean() 属性的,简单说就是具有true 和 false 两个属性的属性,如 checked, selected 或者 disabled 使用prop(),(其实这些都是表单类的), ...
- Windows上的程序员神器Cmder
用过Windows版本Git的都知道Git自带了Git Bash,这个在很大程度上满足了我的需求,随着Git的版本升级越来越好用 安装Cmder Cmder官网,它把conemu,msysgit和cl ...
- 【进阶2-2期】JavaScript深入之从作用域链理解闭包(转)
这是我在公众号(高级前端进阶)看到的文章,现在做笔记 https://github.com/yygmind/blog/issues/18 红宝书(p178)上对于闭包的定义:闭包是指有权访问另外一 ...
- System.TypeInitializationException: The type initializer for 'Oracle.DataAccess.Client.OracleConnection' threw an exception. ---> Oracle.DataAccess.Client.OracleException: 提供程序与此版本的 Oracle 客户机不兼容”
.net应用程序通过Oracle.DataAccess.dll访问64位的Oracle服务器,在连接时出现以下异常:“System.TypeInitializationException: The t ...
- python用unittest+HTMLTestRunner的框架测试并生成测试报告
直接贴代码: import unittestfrom selenium import webdriverfrom time import sleepimport osimport time # 定义打 ...
- Nginx详解十六:Nginx场景实践篇之缓存服务
缓存类型: 服务端缓存 代理缓存 客户端缓存 Nginx代理缓存 配置语法 使用之前需要先定义一个proxy_cache_path配置语法:proxy_cache_path path [levels= ...
- ORACLE EHCC(exadata hybrid columnar compression)
目录: 1. 简介 2. 压缩方式及压缩比 3. 压缩哪些数据 4. 可能有用的脚本 一.简介 EHCC(Exadata Hybrid Columnar Compression),是Oralce 数据 ...
- Python(字符串操作实例1)一个字符串用空格隔开
# 将字符中单词用空格隔开# 已知传入的字符串中只有字母,每个单词的首字母大写,# 请将每个单词用空格隔开,只保留第一个单词的首字母大写传入:“HelloMyWorld”# 返回“Hello my w ...