题意

你有一支由 n 名预备役士兵组成的部队,士兵从 1 到 n 编号,要将他们拆分 成若干特别行动队调入战场。出于默契的考虑,同一支特别行动队中队员的编号 应该连续,即为形如(i, i + 1, ..., i + k)的序列。 编号为 i 的士兵的初始战斗力为 xi ,一支特别行动队的初始战斗力 x 为队内 士兵初始战斗力之和,即$ x = x_i + x_{i+1} + ... + x_{i+k}$。

通过长期的观察,你总结出一支特别行动队的初始战斗力 x 将按如下经验公 式修正为 \(x':x'= ax^2+bx+cx\) ,其中 a, b, c 是已知的系数(a < 0)。 作为部队统帅,现在你要为这支部队进行编队,使得所有特别行动队修正后 战斗力之和最大。试求出这个最大和。

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

\(n \leq 10^6\)

题解

考虑dp,容易列出dp方程

\[dp[i]=\max\{ dp[j] +a(s[i]-s[j])^2 + b(s[i] - s[j]) +c\} (j<i)
\]

\(dp[i]\)表示前\(i\)个的最大修正战斗力,\(s[i]\)是初始战斗力的前缀和。

显然是\(O(n^2)\)的,观察式子,发现可以变形做斜率优化。

令\(j>k\)(这个很重要,保证了除式大于0,至于为什么要这样,那是尝试得出来的),假设\(j\)比\(k\)优,得到

\[dp[j] +as[j]^2 -bs[j] - (dp[k] + as[k]^2 -bs[k]) > 2as[i](s[j]-s[k])
\]

然后这里由于\(a<0\),除过去不利于分析,所以保留在右方,这时\(j > k\)的作用体现出来了,\(s[j] > s[k]\)保证除过去不变号,且横坐标递增。

\[\frac{dp[j] +as[j]^2 -bs[j] - (dp[k] + as[k]^2 -bs[k])}{s[j]-s[k]} > 2as[i]
\]

然后是\(>\)号,且横坐标\(s\)递增,所以维护上凸包。

由于\(a<0\),所以\(2as\)递减,所以可以用单调队列。

简单来说,能用单调队列的是

  1. 大于单调减
  2. 小于单调增

时间复杂度\(O(n)\)


没写`return`,`-Wall`又不知道怎么自动关了,调得很难受。感谢W学姐帮我看出来。
```cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define rg register
#define il inline
#define co const
templateil T read()
{
rg T data=0;
rg int w=1;
rg char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
{
data=data*10+ch-'0';
ch=getchar();
}
return data*w;
}
templateT read(T&x)
{
return x=read();
}
using namespace std;
typedef long long ll;

co int N=1e6+2;

ll a,b,c;

ll x[N];

ll dp[N];

ll Up(int j,int k)

{

return dp[j]+ax[j]x[j]-bx[j]-dp[k]-ax[k]x[k]+bx[k];

}

ll Down(int j,int k)

{

return x[j]-x[k];

}

ll Cal(int i,int j)

{

return dp[j]+a(x[i]-x[j])(x[i]-x[j])+b*(x[i]-x[j])+c; // edit 1: return

}

int q[N];

int main()

{

// freopen(".in","r",stdin);

// freopen(".out","w",stdout);

int n=read();

read(a),read(b),read(c);

for(int i=1;i<=n;++i)

x[i]=x[i-1]+read();

int head=0,tail=0;

q[tail++]=0;

for(int i=1;i<=n;++i)

{

while(head+1<tail&&Up(q[head+1],q[head])>=2ax[i]Down(q[head+1],q[head]))

++head;

dp[i]=Cal(i,q[head]);

while(head+1<tail&&Up(i,q[tail-1])
Down(q[tail-1],q[tail-2])>=Up(q[tail-1],q[tail-2])*Down(i,q[tail-1]))

--tail;

q[tail++]=i;

}

printf("%lld\n",dp[n]);

return 0;

}


20190716:怎么说呢?怪到大样例身上去吧。

LG3628 [APIO2010]特别行动队的更多相关文章

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

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

  2. 【BZOJ 1191】 [Apio2010]特别行动队 (斜率优化)

    dsy1911: [Apio2010]特别行动队 [题目描述] 有n个数,分成连续的若干段,每段的分数为a*x^2+b*x+c(a,b,c是给出的常数),其中x为该段的各个数的和.求如何分才能使得各个 ...

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

    1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3191  Solved: 1450[Submit][Statu ...

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

    sum为战斗力的前缀和 dp(x) = max( dp(p)+A*(sumx-sump)2+B*(sumx-sump)+C )(0≤p<x) 然后斜率优化...懒得写下去了... ------- ...

  5. bzoj1911[Apio2010]特别行动队 斜率优化dp

    1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 5057  Solved: 2492[Submit][Statu ...

  6. 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]= ...

  7. [luogu P3628] [APIO2010]特别行动队

    [luogu P3628] [APIO2010]特别行动队 题目描述 你有一支由 n 名预备役士兵组成的部队,士兵从 1 到 n 编号,要将他们拆分 成若干特别行动队调入战场.出于默契的考虑,同一支特 ...

  8. 【bzoj1911】[Apio2010]特别行动队

    1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 4048  Solved: 1913[Submit][Statu ...

  9. [APIO2010]特别行动队 --- 斜率优化DP

    [APIO2010]特别行动队 题面很直白,就不放了. 太套路了,做起来没点感觉了. \(dp(i)=dp(j)+a*(s(i)-s(j))^{2}+b*(s(i)-s(j))+c\) 直接推出一个斜 ...

随机推荐

  1. 将从数据库中获取的数据写入到Excel表中

    pom.xml文件写入代码,maven自动加载poi-3.1-beta2.jar <!-- https://mvnrepository.com/artifact/poi/poi --> & ...

  2. tesseract 3.05 release 编译

    tesseract 3.05 release版本的对应配置好的vs2015工程.偷懒必备,毕竟依赖那么多库,环境配置还是要费点事的.https://github.com/peirick/VS2015_ ...

  3. Python 中lambda 简单介绍

    转自:https://www.cnblogs.com/AlwaysWIN/p/6202320.html 在学习python的过程中,lambda的语法经常出现,现在将它整理一下,以备日后查看. 1.l ...

  4. 如何理解 Python 中的__init__

    转自https://www.zhihu.com/question/46973549/answer/103805810 定义类的时候,若是添加__init__方法,那么在创建类的实例的时候,实例会自动调 ...

  5. git常用的语句

    下面总结出开发中常用的指令: 1.git init:初始化git仓库 2.git add 文件名:把文件添加到暂存区中 3.git commit -m "提交信息":提交暂存区内容 ...

  6. ceph存储 ceph Bluestore的架构

    ceph 目前是开源社区比较流行的分布式块存储系统,其以良好的架构,稳定性和完善的数据服务功能,获得的了广泛的部署和应用. 目前ceph 最大的问题是其性能相对较差,特别是无法发挥SSD等高速设备的硬 ...

  7. Origin软件作图留白过多问题解决

    解决空白过大方法:1.Tools——>Options2.Page——>Copy page setting——>Margin默认是Page,下拉菜单选Border,Clip Borde ...

  8. spring:设置映射访问路径 或 xml配置访问路径 (spring mvc form表单)

    项目hello, 在src/main/java下面建一个目录: charpter2 一.xml配置访问路径 web.xml <web-app> <display-name>Ar ...

  9. Appium移动自动化测试(三)--自动化测试demo

    使用java语言编写并实现自动化测试实例 前面我已经搭建好了appium所需要的环境,本文我以系统自带的计算器app为测试对象,进行学习. 一.将测试机与PC连接 本人使用的是Android模拟器,测 ...

  10. CSS3的transition和transform

    CSS3中的transition和transform是制作HTML5动画一定要使用到的两个属性. 注:这篇文章不考虑兼容性,只讨论webkit核心的浏览器.所以本文的所有例子请用chrome,safa ...