Lightning Conductor
题目背景:
分析:DP 决策单调性
表示本喵并不会决策单调性·······
首先题目中的绝对值,我们可以通过正向来一次,然后反向来一次然后搞定,所以可以直接去掉绝对值符号了,考虑这个题满足的性质,首先明确一点数学知识,sqrt函数的增长量是随着自变量的增大而减小的,也就是说对于两个数x, y(y > x),sqrt(x + a) – sqrt(x) > sqrt(y + a) – sqrt(y), (a > 0),那么我们可以发现,如果对于一个数i,a[j] + sqrt(i - j) < a[k] + sqrt(i - k), (j< k), 那么j这个决策,对于i和i之后的都将没有用了,因为这个由刚才所说的sqrt函数的性质可以推出,也就是说对于一个数i,找出max(a[j] + sqrt(i - j))的j是满足决策单调性的也就是说对于x > i, f[x]>= f[i],然后我们就可以用决策单调性的模板来解决啦这里采用的整体二分的写法。
Source:
/*
created by scarlyw
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <cctype>
#include <ctime>
inline char read() {
static const int IN_LEN = 1024 * 1024;
static char buf[IN_LEN], *s, *t;
if (s == t) {
t = (s = buf) + fread(buf, 1, IN_LEN, stdin);
if (s == t) return -1;
}
return *s++;
}
/*
template<class T>
inline void R(T &x) {
static char c;
static bool iosig;
for (iosig = false, c = read(); !isdigit(c); c = read()) {
if (c == -1) return ;
if (c == '-') iosig = true;
}
for (x = 0; isdigit(c); c = read())
x = ((x << 2) + x << 1) + (c ^ '0');
if (iosig) x = -x;
}
//*/
///*
template<class T>
inline void R(T &x) {
static char c;
static bool iosig;
for (iosig = false, c = getchar(); !isdigit(c); c = getchar())
if (c == '-') iosig = true;
for (x = 0; isdigit(c); c = getchar())
x = ((x << 2) + x << 1) + (c ^ '0');
if (iosig) x = -x;
}
//*/
const int OUT_LEN = 1024 * 1024;
char obuf[OUT_LEN], *oh = obuf;
inline void write_char(char c) {
if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;
*oh++ = c;
}
template<class T>
inline void W(T x) {
static int buf[30], cnt;
if (x == 0) write_char('0');
else {
if (x < 0) write_char('-'), x = -x;
for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
while (cnt) write_char(buf[cnt--]);
}
}
inline void flush() {
fwrite(obuf, 1, oh - obuf, stdout);
}
const int MAXN = 500000 + 10;
int n;
int a[MAXN], f[MAXN], g[MAXN];
inline void read_in() {
R(n);
for (int i = 1; i <= n; ++i) R(a[i]);
}
inline void solve(int l, int r, int ql, int qr, int *f) {
if (l > r) return ;
double max = 0;
int pos, mid = l + r >> 1;
for (int i = ql; i <= qr && i <= mid; ++i)
if ((double)a[i] + sqrt((double)(mid - i)) >= max)
max = (double)a[i] + sqrt((double)(mid - i)), pos = i;
f[mid] = a[pos] + ceil(sqrt((double)(mid - pos)));
solve(l, mid - 1, ql, pos, f), solve(mid + 1, r, pos, qr, f);
}
int main() {
read_in();
solve(1, n, 1, n, f);
std::reverse(a + 1, a + n + 1);
solve(1, n, 1, n, g);
for (int i = n; i >= 1; --i)
W(std::max(f[n + 1 - i], g[i]) - a[i]), write_char('\n');
flush();
return 0;
}