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. python print和strip

    在使用这两个模块时犯过错误,总结如下: 1.print print在打印时会自动加上换行,例如: >>> for i in xrange(1,5): ... print i ... ...

  2. 监控控制台是否运行的bat

    @echo offrem set secs=5set srvname="TRS.Export.Scheduler.exe" echo.echo ================== ...

  3. Struts2 入门实例

    一.最简登录 Demo:login.jsp——web.xml——struts.xml——LoginAction.java——struts.xml——index.jsp 1.下载 Struts2 框架: ...

  4. Helper Files

    常用帮助类 C#语法糖 Net 通用工具类 Helloweba Front Program Resources jqGrid   Highcharts  jQuery实现的加载页面过渡效果   jQu ...

  5. ubuntu mac terminal install software

    http-server // ubuntu sudo npm install http-server -g npm node.js yarn

  6. Java分支结构 - if...else/switch

    Java分支结构 - if...else/switch 顺序结构只能顺序执行,不能进行判断和选择,因此需要分支结构. Java有两种分支结构: if语句 switch语句 if语句 一个if语句包含一 ...

  7. Python之路,Day9 - 线程、进程、协程和IO多路复用

    参考博客: 线程.进程.协程: http://www.cnblogs.com/wupeiqi/articles/5040827.html http://www.cnblogs.com/alex3714 ...

  8. fzu Problem 2275 Game(kmp)

    Problem 2275 Game Accept: 62    Submit: 165Time Limit: 1000 mSec    Memory Limit : 262144 KB  Proble ...

  9. 如何让VS2013编写的程序在xp下运行

    总体分c++程序和c#程序 1.c++程序 这个用C++编写的程序可以经过设置后在XP下运行,主要的“平台工具集”里修改就可以. 额外说明:(1)程序必须为Dotnet 4.0及以下版本.(XP只支持 ...

  10. avr 烧录失败

    用Atmel studio 6.0 配置mkII烧录器 使用上位机bat程序烧录 提示错误:firmware is old... 1参考(关于FUSe setting) http://www.cnbl ...