bzoj2216 Lightning Conductor

Lightning Conductor

题目背景:

bzoj2216

分析:DP 决策单调性

表示本喵并不会决策单调性·······

首先题目中的绝对值,我们可以通过正向来一次,然后反向来一次然后搞定,所以可以直接去掉绝对值符号了,考虑这个题满足的性质,首先明确一点数学知识,sqrt函数的增长量是随着自变量的增大而减小的,也就是说对于两个数x, y(y > x)sqrt(x + a)  sqrt(x) > sqrt(y + a)  sqrt(y), (a > 0),那么我们可以发现,如果对于一个数ia[j] + sqrt(i - j) < a[k] + sqrt(i - k), (j< k), 那么j这个决策,对于ii之后的都将没有用了,因为这个由刚才所说的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;
}


 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值