Lightning Conductor 洛谷P3515 决策单调性优化DP
遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森。
先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬。
废话不多说,看题:
题目大意
已知一个长度为n的序列a1,a2,...,an。
对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p - sqrt(abs(i-j))
数据范围
洛咕上也没给,我能怎么办啊
非正解做法一:暴力
应该都会吧,\(O(n^2)\)枚举。洛谷上貌似40pts。
非正解做法二:ST表优化
首先,我们将原式整理,可得\(p\geqslant a_j-a_i+\sqrt{\left | i-j \right |}\),最终\(p_i\)即是\(max\{\left \lceil a_j-a_i+\sqrt{\left | i-j \right |} \right \rceil \}\)。
然后,我们发现,其实需要向上取整的只有\(\sqrt{\left | i-j \right |}\)这一部分,而它向上取整的值是连续分布的,即0,1,2,2,2,3,3,3,3,3,4......且如果知道i和j的值时,我们很容易知道同一个数开始的位置和结束的位置。
然后我们就可以用ST表来维护区间最大值,预计得分50pts。
(我没想到的)正解
经过观察式子,我们知道\(p_i\)的值取决于\(a_j+\sqrt{\left | i-j \right |}\),现在,我们记这个值为\(f_j\),且\(f_j\)是关于i的一个函数,\(i\geqslant j\)。那么,所有的\(f_j\)大概会长成这个样子:
不难看出,每个\(f_j\)都是单调递增的,形状都是一样的(但定义域和值域不同),且斜率越来越小(这貌似叫上凸?)。
但是如果函数长成这张图那样,我们真正需要的只有上面的那一条绿线。
假设在程序中我们有了这张图,问题就变得hin简单,用最高的那个函数一算就可以辣(比如这张图就是上面那个黄色的)。
于是,问题转化为如何找出最高的那个\(f_j\)了。\(f_j\)还有一个很好的性质,就是对于最高的那个\(f_j\),它的巅峰时期绝对是一段连续的区间(因为上凸嘛),且最高的那条一定是在某两条函数图像的交点处改变的。
然后,我们发现这个东西用单调队列很好维护,我们可以顺带求出i位置的答案。此处令\(cur\)为当前枚举到的\(j\),\(q\)为单调队列(存的是\(j\)),\(h\)为队头指针,\(t\)为队尾指针,\(isx[i]\)为队列中第\(i\)个\(f_j\)与队列中第\(i+1\)个\(f_j\)的交点横坐标,\(intersectionX(i,j)\)返回的是\(f_i\)与\(f_j\)交点的横坐标。我们先按\(j\)从小到大把\(j\)加入,但我们要怎样维持队列的单调性呢?
1.当\(isx[t-1] \geqslant intersectionX(q[t],cur)\)时,那么就可以把\(q[t]\)弹出(想一想,画一下图就很清楚了)
2.把\(j\)插入到队尾
3.当\(isx[h] \leqslant cur\)时,那么就可以把\(q[h]\)弹出(显然嘛)
操作完后,\(q[h]\)就是我们要的最高的\(f_j\)的\(j\)了,然后我们就可以更新\(i\)位置的答案啦。
那么\(intersectionX(i,j)\)该怎样求呢?因为问题是定义在正整数域上的,我们就二分一下。
最后,注意一下砸,因为我们要从小到大加入j,而枚举点可能会在中间,所以我们要正着跑一遍,再倒着跑一遍,两遍取一下\(max\)。
上代码:
#include <bits/stdc++.h>
using namespace std;
#define re register
#define N 20000000
int n, isx[N+5], q[N+5], a[N+5];
double f[N+5]; //答案数组
double calc(int x, int y) { //计算a[y]+sqrt(x-y)
return a[y]+sqrt(double(x)-y);
}
int intersection(int f1, int f2) {
int l = 1, r = n, mid, ret = r+1; //ret要设成n+1,因为在1~n中可能没有交点
while(l <= r) { //二分交点
mid = (l+r)/2;
if(calc(mid, f1) <= calc(mid, f2)) ret = mid, r = mid-1;
else l = mid+1;
}
return ret;
}
void solve() {
for(re int h = 1, t = 0, i = 1; i <= n; ++i) {
while(h < t && isx[t-1] >= intersection(q[t], i)) --t; //队尾删除操作
isx[t] = intersection(q[t], i), q[++t] = i; //插入到队尾
while(h < t && isx[h] <= i) ++h; //队头弹出操作
f[i] = max(f[i], calc(i, q[h])); //更新答案
}
}
int main() {
ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n;
for(re int i = 1; i <= n; ++i) cin >> a[i];
solve();
for(re int i = 1, j = n; i < j; ++i, --j) swap(a[i], a[j]), swap(f[i], f[j]); //反转序列
solve();
for(re int i = n; i >= 1; --i) cout << ceil(f[i])-a[i] << endl; //计算答案
return 0;
}
Lightning Conductor 洛谷P3515 决策单调性优化DP的更多相关文章
- 洛谷P3515 [POI2011]Lightning Conductor(动态规划,决策单调性,单调队列)
洛谷题目传送门 疯狂%%%几个月前就秒了此题的Tyher巨佬 借着这题总结一下决策单调性优化DP吧.蒟蒻觉得用数形结合的思想能够轻松地理解它. 首先,题目要我们求所有的\(p_i\),那么把式子变一下 ...
- BZOJ2216 Poi2011 Lightning Conductor 【决策单调性优化DP】
Description 已知一个长度为n的序列a1,a2,...,an. 对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p - sqrt( ...
- 决策单调性优化dp 专题练习
决策单调性优化dp 专题练习 优化方法总结 一.斜率优化 对于形如 \(dp[i]=dp[j]+(i-j)*(i-j)\)类型的转移方程,维护一个上凸包或者下凸包,找到切点快速求解 技法: 1.单调队 ...
- CF868F Yet Another Minimization Problem 分治决策单调性优化DP
题意: 给定一个序列,你要将其分为k段,总的代价为每段的权值之和,求最小代价. 定义一段序列的权值为$\sum_{i = 1}^{n}{\binom{cnt_{i}}{2}}$,其中$cnt_{i}$ ...
- 2018.09.28 bzoj1563: [NOI2009]诗人小G(决策单调性优化dp)
传送门 决策单调性优化dp板子题. 感觉队列的写法比栈好写. 所谓决策单调性优化就是每次状态转移的决策都是在向前单调递增的. 所以我们用一个记录三元组(l,r,id)(l,r,id)(l,r,id)的 ...
- [BZOJ4850][JSOI2016]灯塔(分块/决策单调性优化DP)
第一种方法是决策单调性优化DP. 决策单调性是指,设i>j,若在某个位置x(x>i)上,决策i比决策j优,那么在x以后的位置上i都一定比j优. 根号函数是一个典型的具有决策单调性的函数,由 ...
- 洛谷 P5897 - [IOI2013]wombats(决策单调性优化 dp+线段树分块)
题面传送门 首先注意到这次行数与列数不同阶,列数只有 \(200\),而行数高达 \(5000\),因此可以考虑以行为下标建线段树,线段树上每个区间 \([l,r]\) 开一个 \(200\times ...
- 算法学习——决策单调性优化DP
update in 2019.1.21 优化了一下文中年代久远的代码 的格式…… 什么是决策单调性? 在满足决策单调性的情况下,通常决策点会形如1111112222224444445555588888 ...
- BZOJ4899: 记忆的轮廓【概率期望DP】【决策单调性优化DP】
Description 通往贤者之塔的路上,有许多的危机. 我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增, 在[1,n]中,一共有n个节点.我 ...
随机推荐
- linux下的qt串口通信
1.linux下的qt串口通信跟windows唯一的差别就是端口号的名字,windows下面是COM,而linux是ttyUSB0的路径 2.一般情况下linux插上USB转串口线就可以在/dev/目 ...
- Centos7.5 部署postfix邮件系统
1. Postfix 1.1 邮件服务的介绍 电子邮件是—种用电子手段提供信息交换的通信方式,是互联网应用最广的服务.通过网络的电子邮件系统,用户可以以非常低廉的价格(不管发送到哪里,都只需负担网费) ...
- 二、Windows Server 2016 AD 组织单位、组、用户的创建
简介: 组织单位简称OU,OU是(Organizational Unit)的缩写,组织单位是可以将用户.组.计算机和组织单位放入其中的容器.是可以指派组策略设置或委派管理权限的最小作用域或单元. 建立 ...
- 阿里云上的Centos 7.6的一次Nginx+Mysql+PHP7.3 部署
阿里云申请了一台服务器 Centos 7.6,每次安装都要上网找一大堆教程,因为不熟悉,因为总是忘记. 所以,有时间的时候,还是记录下自己的学习过程,有助于下次的问题解决. 我先总结下: 1)安装VS ...
- Dynamics 365 CRM 开发架构简介
Dynamics 365 CRM提供了多种编程模型,你可以灵活地按需选用最佳模式. 本文是对Dynamics 365 CRM编程模型的综述. 概览 下图表明了Dynamics 365 CRM的主要可编 ...
- Spring boot admin 节点状态一直为DOWN的排查
项目中需要监控各个微服务节点的健康状态,找到了spring boot admin这个全家桶监控工具,它其实是Vue.js美化过的Spring Boot Actuator,官方的解释是: codecen ...
- Enterprise Architect 时序图
添加时序图 1,在类图下面新建包 添加sequence时序图 点击流程控制,可以打开流程控制设计界面 我选择的是Lifeline线,你可以选择都差不多. 点击其中一条liftline连到其他上面 双击 ...
- Linux安装python2.7
一.Python安装 以Python-2.7.7为例,安装包:Python-2.7.7.tgz如无特殊说明,以下安装步骤都采用root用户执行 1. 解压Python-2.7.7.tgz tar -x ...
- echarts堆叠图添加总量
echarts在使用中往往会遇到需要展示总量信息的情况,比较典型的就是3维统计的堆叠柱状图 堆叠是在柱状图的基础上,给几项设置同一stack来实现的.不考虑在tips中实现总和,有两种方式可以实现总和 ...
- Spring事件和监听器
Application下抽象子类ApplicationContextEvent的下面有4个已经实现好的事件 ContextClosedEvent(容器关闭时) ContextRefreshedEven ...