题目描述

你有一支由nnn名预备役士兵组成的部队,士兵从1到nnn编号,要将他们拆分成若干特别行动队调入战场。出于默契考虑,同一支特别行动队中队员的编号应该连续,即为形如(i,i+1,...,i+k)(i,i+1,...,i+k)(i,i+1,...,i+k)的序列。

编号为iii的士兵的初始战斗力为xi,一支特别运动队的初始战斗力xxx为队内士兵初始战斗力之和,即x=xi+xi+1+...+xi+kx=x_i+x_{i+1}+...+x_{i+k}x=xi​+xi+1​+...+xi+k​。

通过长期的观察,你总结出一支特别行动队的初始战斗力x将按如下经验公式修正为x′x'x′:x′=ax2+bx+cx'=ax^2+bx+cx′=ax2+bx+c,其中a,b,ca,b,ca,b,c是已知的系数(a&lt;0)(a&lt;0)(a<0)。

作为部队统帅,现在你要为这支部队进行编队,使得所有特别行动队修正后战斗力之和最大。试求出这个最大和。

例如,你有4名士兵,x1=2,x2=2,x3=3,x4=4x_1=2,x_2=2,x_3=3,x_4=4x1​=2,x2​=2,x3​=3,x4​=4。经验公式中的参数为a=−1,b=10,c=−20a=-1,b=10,c=-20a=−1,b=10,c=−20。此时,最佳方案是将士兵组成3个特别行动队:第一队包含士兵1和士兵2,第二队包含士兵3,第三队包含士兵4。特别行动队的初始战斗力分别为4,3,4,修正后的战斗力分别为4,1,4。修正后的战斗力和为9,没有其它方案能使修正后的战斗力和更大。

分析

根据题意,可以容易得到朴素的状态转移方程:

f[i]=max⁡0≤j&lt;i{f[j]+a×(sum[i]−sum[j])2+b×(sum[i]−sum[j])+c}f[i]=\max_{0\le j&lt;i}\{f[j]+a\times(sum[i]-sum[j])^2+b\times(sum[i]-sum[j])+c\} f[i]=0≤j<imax​{f[j]+a×(sum[i]−sum[j])2+b×(sum[i]−sum[j])+c}

其中sumsumsum表示前缀和。将其展开,会得到i,ji,ji,j的乘积项,因此想到斜率优化Dp。

对于j,k,若在j处的决策比k处的更优,则:

f[j]+a×(sum[i]−sum[j])2+b×(sum[i]−sum[j])+c&gt;f[k]+a×(sum[i]−sum[k])2+b×(sum[i]−sum[k])+c\begin{matrix} f[j]+a\times(sum[i]-sum[j])^2+b\times(sum[i]-sum[j])+c&gt;\\ f[k]+a\times(sum[i]-sum[k])^2+b\times(sum[i]-sum[k])+c \end{matrix} f[j]+a×(sum[i]−sum[j])2+b×(sum[i]−sum[j])+c>f[k]+a×(sum[i]−sum[k])2+b×(sum[i]−sum[k])+c​

化简可得

f[j]−f[k]+a×(sum[j]2−sum[k]2)+b×(sum[k]−sum[j])&gt;2×a×sum[i]×(sum[j]−sum[k])f[j]-f[k]+a\times(sum[j]^2-sum[k]^2)+b\times(sum[k]-sum[j])&gt;2\times a\times sum[i]\times(sum[j]-sum[k]) f[j]−f[k]+a×(sum[j]2−sum[k]2)+b×(sum[k]−sum[j])>2×a×sum[i]×(sum[j]−sum[k])

所以维护一个单调队列,每次将队首和队首+1进行比较,若不满足上式,则将队首出队,直到满足,此时即为最优的决策。再更新当前的最优值。然后将队尾-1与队尾和队尾与iii进行比较,若不满足,则队尾出队,直到满足,此时将iii加入队列中。最后输出f[n]f[n]f[n]即可。

代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define pp(x) ((x)*(x))
using namespace std;
long long f[1000001],n;
long long a,b,c,sum[1000001];
long long head,tail,q[1000005];
int main() {scanf("%lld%lld%lld%lld",&n,&a,&b,&c);for (int i=1;i<=n;i++) {long long t;scanf("%lld",&t);sum[i]=sum[i-1]+t;}memset(f,-0x3f,sizeof(f));f[0]=0;head=tail=1;q[head]=0;for (int i=1;i<=n;i++) {while (head<tail&&f[q[head]]-f[q[head+1]]+a*(pp(sum[q[head]])-pp(sum[q[head+1]]))+b*(sum[q[head+1]]-sum[q[head]])<=2*a*sum[i]*(sum[q[head]]-sum[q[head+1]])) head++;f[i]=f[q[head]]+a*pp(sum[i]-sum[q[head]])+b*(sum[i]-sum[q[head]])+c;while (head<tail&&(f[q[tail-1]]-f[q[tail]]+a*(pp(sum[q[tail-1]])-pp(sum[q[tail]]))+b*(sum[q[tail-1]]-sum[q[tail]]))*(sum[q[tail]]-sum[i])<=(f[q[tail]]-f[i]+a*(sum[q[tail]]*sum[q[tail]]-sum[i]*sum[i])+b*(sum[q[tail]]-sum[i]))*(sum[q[tail-1]]-sum[q[tail]])) tail--;q[++tail]=i;}printf("%lld",f[n]);return 0;
}

「APIO2010」 特别行动队 - 斜率优化Dp相关推荐

  1. APIO2010 特别行动队 斜率优化DP算法笔记

    做完此题之后 自己应该算是真正理解了斜率优化DP 根据状态转移方程$f[i]=max(f[j]+ax^2+bx+c),x=sum[i]-sum[j]$ 可以变形为 $f[i]=max((a*sum[j ...

  2. 【bzoj1911】[Apio2010]特别行动队 斜率优化dp

    题目描述 输入 输出 样例输入 4 -1 10 -20 2 2 3 4 样例输出 9 题解 斜率优化dp 设f[i]表示前i个士兵的战斗力之和的最大值. 那么有f[i]=f[j]+a*(sum[i]- ...

  3. [APIO2010]特别行动队——[斜率优化DP]

    [题目描述] 你有一支由 n 名预备役士兵组成的部队,士兵从 1 到 n 编号,要将他们拆分 成若干特别行动队调入战场.出于默契的考虑,同一支特别行动队中队员的编号 应该连续,即为形如(i,i+1,. ...

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

    1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 4142  Solved: 1964 [Submit][Sta ...

  5. BZOJ 2149 拆迁队 斜率优化DP 主席树

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2149 题目大意: 一个长度为 n n的序列aa,改变其中的某些数使之成为一个单调递增序列, ...

  6. bzoj 1911: [Apio2010]特别行动队 -- 斜率优化

    1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MB Description Input Output Sample Input 4 ...

  7. 特别行动队-斜率优化

    APIO2010特别行动队 令S为前缀和,那么n方DP: f[i]=max{f[i],f[j]+a*(S[i]-S[j])*(S[i]-S[j])+b*(S[i]-S[j])+c}; 展开,移项得到: ...

  8. 特别行动队[斜率优化]

    传送门 首先考虑暴力的DP sum(i--j) 可以用前缀和维护 把式子拆开 ...是一坨常数,这里省略了 我们令 y=f[j]+a*s[j]*s[j]-b*s[j]  ,  x=s[j]  ,  k ...

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

    2149: 拆迁队 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 397  Solved: 177 [Submit][Status][Discuss ...

最新文章

  1. linux安装语言总是waiting,node的serialport在arm的Linux安装血泪史之我太难了
  2. FD.io/VPP — VNF 应用场景
  3. 免费下载 |《数据分析从理念到实操》白皮书上线!先收藏!
  4. python字符串库函数_Python标准库概览(1):string
  5. @slf4j注解_SpringBoot + Redis + 注解 + 拦截器 实现接口幂等性校验
  6. 优化matlab作业,现代设计优化算法MATLAB实现
  7. JQuery EasyUI入门
  8. 旋转角度_LG推出新款显示器,可多角度旋转
  9. MySQL(6)--- 创建数据库
  10. 观电影《头号玩家》有感
  11. TFTP 简单文件传输协议 简介
  12. vb.net中的换行
  13. TensorRT学习(1):通过pth生成wts文件
  14. 最受欢迎的30款开源软件
  15. python飞机大战实验报告心得_飞机大战实训报告
  16. 阿里巴巴图标库(iconfont)使用
  17. QT——开发入门简介
  18. 剑指offer之二叉搜索树的后序遍历序列
  19. kotlin “${ }”是什么意思?
  20. HEVC Study Three(基于HM14.0平台)--GOP研究之大揭秘

热门文章

  1. 超级搞笑----英语翻译的最高境界
  2. Python+AI给老照片上色
  3. 关于embed标签显示pdf(angularjs为前端)
  4. Python 排列组合的计算
  5. ChatGPT基础用法及使用场景
  6. 计算机博士入学考试英语,博士生考试_考博与考研的区别(以计算机考博为例)_沪江英语...
  7. 网络安全难学吗?怎么系统学习网络安全?
  8. WebService常见问题总结
  9. Qt设置label的文字自动换行、高度随内容调整、上下可滚动
  10. extends的含义java_extends在java中什么意思