LG3628 [APIO2010]特别行动队
题意
你有一支由 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]\)表示前\(i\)个的最大修正战斗力,\(s[i]\)是初始战斗力的前缀和。
显然是\(O(n^2)\)的,观察式子,发现可以变形做斜率优化。
令\(j>k\)(这个很重要,保证了除式大于0,至于为什么要这样,那是尝试得出来的),假设\(j\)比\(k\)优,得到
\]
然后这里由于\(a<0\),除过去不利于分析,所以保留在右方,这时\(j > k\)的作用体现出来了,\(s[j] > s[k]\)保证除过去不变号,且横坐标递增。
\]
然后是\(>\)号,且横坐标\(s\)递增,所以维护上凸包。
由于\(a<0\),所以\(2as\)递减,所以可以用单调队列。
简单来说,能用单调队列的是
- 大于单调减
- 小于单调增
时间复杂度\(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]特别行动队的更多相关文章
- BZOJ 1911: [Apio2010]特别行动队 [斜率优化DP]
1911: [Apio2010]特别行动队 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 4142 Solved: 1964[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) 然后斜率优化...懒得写下去了... ------- ...
- bzoj1911[Apio2010]特别行动队 斜率优化dp
1911: [Apio2010]特别行动队 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 5057 Solved: 2492[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]= ...
- [luogu P3628] [APIO2010]特别行动队
[luogu P3628] [APIO2010]特别行动队 题目描述 你有一支由 n 名预备役士兵组成的部队,士兵从 1 到 n 编号,要将他们拆分 成若干特别行动队调入战场.出于默契的考虑,同一支特 ...
- 【bzoj1911】[Apio2010]特别行动队
1911: [Apio2010]特别行动队 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 4048 Solved: 1913[Submit][Statu ...
- [APIO2010]特别行动队 --- 斜率优化DP
[APIO2010]特别行动队 题面很直白,就不放了. 太套路了,做起来没点感觉了. \(dp(i)=dp(j)+a*(s(i)-s(j))^{2}+b*(s(i)-s(j))+c\) 直接推出一个斜 ...
随机推荐
- P4949 最短距离(基环树+树链剖分)
题目 P4949 最短距离 做法 先把非树边提出来 查询\((x,y)\)的最短距离就分类查询:树上\((x,y)\)距离,经过非树边距离 带边权查询链长,一个烂大街的套路:树链剖分,节点维护树边距离 ...
- Zabbix Windos mysql 监控脚本
说明:判断mysql主进程是否关闭,如果关闭则返回0 创建文件:MySQL-ping.vbs Set objFS = CreateObject("Scripting.FileSystemOb ...
- SpringBoot Lombok
简介 lombok是一个编译级别的插件,它可以在项目编译的时候生成一些代码.比如日常开发过程中需要生产大量的JavaBean文件,每个JavaBean都需要提供大量的get和set方法,如果字段较多且 ...
- [Android]自定义控件LoadMoreRecyclerView
RecyclerView是加强版的ListView,用于在有限的窗口中展示大量的数据,而LoadMoreRecyclerView则是为RecyclerView增加了加载更多的功能,先来看效果: 三种加 ...
- vi使用技巧(转载)
http://www.cnblogs.com/xusir/p/3245007.html 这是转载的链接
- MySQL数据库中tinyint类型字段读取数据为true和false (MySQL的boolean和tinyint(1))
数据库一个表中有一个tinyint类型的字段,值为0或者1,如果取出来的话,0会变成false,1会变成true. MySQL保存boolean值时用1代表TRUE,0代表FALSE.boolean在 ...
- Java内存分析1 - 从两个程序说起
这次看一些关于JVM内存分析的内容. 两个程序 程序一 首先来看两个程序,这里是程序一:JVMStackTest,看下代码: package com.zhyea.robin.jvm; public c ...
- scala学习手记8 - 自适应的默认做法
scala有一些默认做法,会让代码更简洁.更易读写,下面列出了这样几个特性: 1. 支持脚本.scala支持脚本,因此无须将所有的代码都放到类里.如果脚本可以满足需求,就将代码放到一个脚本里,无须再创 ...
- 虚拟主机(多站点配置)的实现--centos上的实现
Apache中配置多主机多站点,可以通过两种方式实现 将同一个域名的不同端口映射到不同的站点(虚拟主机) 将同一个端口映射成不同的域名,不同的域名映射到不同的站点 两种方法可以同时存在,局域网通过 ...
- B树, B-树,B+树,和B*树的区别
B树: B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中: 否则,如果查询关键字比结点关键字小,就进入左儿子:如果比结点关键字大,就进入 右儿子:如果左儿子或右儿子的指针为空, ...