Description

已知一个长度为n的序列a1,a2,...,an。

对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p - sqrt(abs(i-j))

Input

第一行n,(1<=n<=500000)

下面每行一个整数,其中第i行是ai。(0<=ai<=1000000000)

Output

n行,第i行表示对于i,得到的p

Sample Input

6

5

3

2

4

2

4

Sample Output

2

3

5

3

5

4


决策单调性优化DP

。。。调了一晚上,都要自闭了


首先可以发现根号函数是一个增长越来越慢的函数

所以一个点如果不能对答案造成贡献,那么他永远都不能造成贡献了

然后就考虑怎么维护这个东西

首先正反跑两遍然后取max这个思路非常显然

现在可以考虑怎么维护单次的贡献

因为对于i,需要最大化

\(h_j - h_i + sqrt(i-j)\)

所以我们可以把原序列划分成一些区间

使得这些区间可以取到最大值

然后每次统计贡献直接在区间上查找就可以了

考虑维护一个队列来维护\([i,n]\)这个区间的所有最优区间

每个节点用三元组\([l,r,pos]\)表示

代表在\([l,r]\)这个区间里面pos可以贡献最大值

然后直接每次看一看如果当前新加入的节点是可以完全包含末尾区间,直接弹出,知道不能操作

这时如果序列为空直接加入\([i,n,i]\)

否则把最后一个区间划分成两个区间进行操作就可以了


注意统计贡献的时候参数顺序很重要


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define for_up(a, b, c) for (int a = b; a <= c; ++a)
#define for_down(a, b, c) for (int a = b; a >= c; --a)
#define for_vector(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-')c = getchar();
if (c == '-')w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9)Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 500010;
const double eps = 1e-5;
int n, l, r;
int dp[N] = {0}, h[N];
struct Node {
int l, r, pos;
Node(){}
Node(int l, int r, int pos):l(l), r(r), pos(pos){}
}p[N];
double cal(int a, int b) { // 一定注意顺序 是统计 a覆盖b的最小高度
return (double)h[b] + sqrt(abs(a - b)) - (double)h[a];
}
int find(Node t, int x) {
int l = t.l, r = t.r, ans = 0;
while (l <= r) {
int mid = (l + r) >> 1;
if(cal(mid, t.pos) <= cal(mid, x)) r = mid - 1, ans = mid;
else l = mid + 1;
}
return ans;
}
void solve(bool typ) {
int l = 1, r = 0;
for_up(i, 1, n) {
if (l <= r && ++p[l].l > p[l].r) ++l;
if (l > r || cal(n, i) > cal(n, p[r].pos)) {
// p[r] 无论如何不会比i优 直接弹掉
while (l <= r && cal(p[r].l, p[r].pos) < cal(p[r].l, i)) --r;
int now = (l > r) ? i : find(p[r], i);
if (l <= r) p[r].r = now - 1;// 如果上一个区间存在 更新右端点
p[++r] = (Node){now, n, i};
}
int id = typ ? n - i + 1 : i;
dp[id] = max(dp[id], (int)ceil(cal(i, p[l].pos)));
}
}
int main() {
Read(n);
for_up(i, 1, n) Read(h[i]);
solve(0);
reverse(h + 1, h + n + 1);
solve(1);
for_up(i, 1, n) {
Write(dp[i]);
putchar('\n');
}
return 0;
}

BZOJ2216 Poi2011 Lightning Conductor 【决策单调性优化DP】的更多相关文章

  1. P3515 [POI2011]Lightning Conductor[决策单调性优化]

    给定一序列,求对于每一个$a_i$的最小非负整数$p_i$,使得$\forall j \neq i $有$ p_i>=a_j-a_i+ \sqrt{|i-j|}$. 绝对值很烦 ,先分左右情况单 ...

  2. 【BZOJ2216】[Poi2011]Lightning Conductor 决策单调性

    [BZOJ2216][Poi2011]Lightning Conductor Description 已知一个长度为n的序列a1,a2,...,an.对于每个1<=i<=n,找到最小的非负 ...

  3. LOJ2074/2157 JSOI2016/POI2011 Lightning Conductor 决策单调性DP

    传送门 我们相当于要求出\(f_i = \max\limits_{j=1}^{n} (a_j + \sqrt{|i-j|})\).这个绝对值太烦人了,考虑对于\(i>j\)和\(i<j\) ...

  4. Lightning Conductor 洛谷P3515 决策单调性优化DP

    遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森. 先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬. 废话不多说,看题: 题目大意 已知一个长度为n的序 ...

  5. 决策单调性优化dp 专题练习

    决策单调性优化dp 专题练习 优化方法总结 一.斜率优化 对于形如 \(dp[i]=dp[j]+(i-j)*(i-j)\)类型的转移方程,维护一个上凸包或者下凸包,找到切点快速求解 技法: 1.单调队 ...

  6. CF868F Yet Another Minimization Problem 分治决策单调性优化DP

    题意: 给定一个序列,你要将其分为k段,总的代价为每段的权值之和,求最小代价. 定义一段序列的权值为$\sum_{i = 1}^{n}{\binom{cnt_{i}}{2}}$,其中$cnt_{i}$ ...

  7. 2018.09.28 bzoj1563: [NOI2009]诗人小G(决策单调性优化dp)

    传送门 决策单调性优化dp板子题. 感觉队列的写法比栈好写. 所谓决策单调性优化就是每次状态转移的决策都是在向前单调递增的. 所以我们用一个记录三元组(l,r,id)(l,r,id)(l,r,id)的 ...

  8. [BZOJ4850][JSOI2016]灯塔(分块/决策单调性优化DP)

    第一种方法是决策单调性优化DP. 决策单调性是指,设i>j,若在某个位置x(x>i)上,决策i比决策j优,那么在x以后的位置上i都一定比j优. 根号函数是一个典型的具有决策单调性的函数,由 ...

  9. BZOJ_2216_[Poi2011]Lightning Conductor_决策单调性

    BZOJ_2216_[Poi2011]Lightning Conductor_决策单调性 Description 已知一个长度为n的序列a1,a2,...,an. 对于每个1<=i<=n, ...

随机推荐

  1. fio测试freenas共享的iscsi磁盘性能

    4k随机读iops: fio -ioengine=libaio -bs=4k -direct=1 -thread -rw=randread -filename=/dev/sdb -iodepth=32 ...

  2. MySQL设置某一字段默认为0,但是插入数据化却显示为null

    1.MySQL字段默认的含义:在插入时不指定该字段的值:2.以mybatis举例,如果是插入实体,那么为空的字段就会插入空:3.如果不想mybatis等持久化工具插入空,可以尝试insertSelec ...

  3. [嵌入式培训笔记]----Linux命令简介

    Linux文件系统的结构类似一棵树,是从一个树根生长出来的.树根叫做/.从树根长出很多分叉,就这么一直生长下去.我们使用Linux操作系统的时候总是落在某个分叉上.ls命令可以帮助我们查看当前分叉上所 ...

  4. Lua学习笔记2. lua变量和 循环

    1. lua中变量的作用域有三种:全局,局部,表中的域 需要注意的是默认的变量都是全局变量,必须声明为local的变量才是局部变量,即使是在函数里面没有使用local修饰的变量依然是全局变量!!!! ...

  5. Hibernate中"二级缓存"配置

    实体类 : package cn.happy.entity; public class Emp { private Integer empNo; private String empName; pub ...

  6. POJ 2369 Permutations (置换的秩P^k = I)

    题意 给定一个置换形式如,问经过几次置换可以变为恒等置换 思路 就是求k使得Pk = I. 我们知道一个置换可以表示为几个轮换的乘积,那么k就是所有轮换长度的最小公倍数. 把一个置换转换成轮换的方法也 ...

  7. bzoj 3197

    题解: 先找到中信 然后dp 代码: #include<bits/stdc++.h> using namespace std; ; ],a[N],b[N],s[N],c[N],f[N]; ...

  8. LeetCode OJ:Letter Combinations of a Phone Number(数字字母组合)

    Given a digit string, return all possible letter combinations that the number could represent. A map ...

  9. set类型以及其操作

    sets类型 sets类型以及操作Set是无序集合,它是string类型的无序集合.set是通过hash table实现的,添加.删除和查找的复杂度都是0(1).对集合我们可以取并集.交集.差集.通过 ...

  10. 字符串-----KMP竟然是18禁

    今天学了一下午字符串,讲到结束也没讲KMP.有人问老师为什么不讲,老师来一句:字符串noip不考,而且还是18禁,自然不讲.[手动滑稽] 所以我也不讲.[微笑] 1.表达式树 表示3+5*8 最后计算 ...