P3515 [POI2011]Lightning Conductor

首先进行一步转化

\(a_j \leq a_i + q - sqrt(abs(i - j))\)

\(a_i + q \geq a_j + sqrt(abs(i-j))\)

即 $q = max (a_j + sqrt(abs(i-j))) - a_i $

我们对\(i \geq j 和 j > i\) 分类讨论, 其实解决一种情况后将序列翻转再做一遍即可

有一种O(\(n^2\))的dp暴力应该不难想到

那么我们现在思考如何以比较优秀的时间复杂度解决

这里涉及到决策单调性

简单的说, 对于i来说, 它的答案来源是另一点j,

那么所有答案来源排成的序列\(j_1,j_2,j_3,\cdots j_n\) 具有单调性

比如: 1112255566666666678888

那么我们可以考虑对于每一个i, 它可以成为哪一段区间的答案

即一个三元组(l, r, i) 对应i控制l到r

可以二分+栈(或队列)处理

二分i和栈顶答案相等临界, 若临界小于l则弹栈重复操作

否则将新的(l, r, i) 压倒栈中

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#define ll long long
using namespace std;
const int N = 500080;
struct node{
	ll l, r, x;
};
deque<node> q;
ll read() {
	ll x = 0, f = 1;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-') f = -1;
		c = getchar();
	}
	while (isdigit(c)) {
		x = (x << 3) + (x << 1) + c - '0';
		c = getchar();
	}
	return x * f;
} //快读
ll n;
long double ans[N], a[N];
bool check(ll x,ll y,ll k) {
	return a[x] + sqrt(k - x) > a[y] + sqrt(k - y);
}
void work(void) {
	node k = (node){1, n, 1}; 
	for (ll i = 2;i <= n; i++) {
		if (a[i] < a[k.x]) continue; //剪枝, 如果满足则它一定不会有贡献
		ll l = i, r = n, mid;
		while (l <= r) {
			mid = (l + r) >> 1;
			if (check(k.x, i, mid)) l = mid + 1;
			else r = mid - 1;
		}//二分
		if (l == n + 1) continue;
		if (l <= k.l) {
			k = q.front();
			q.pop_front();
			i--;
			continue;
		}//弹栈
		k.r = r;
		q.push_front(k);
		k = (node){l, n, i}; //压栈
	}
	q.push_front(k);
	k = q.back();
	q.pop_back();
	for (ll i = 1;i <= n; i++) {
		if (k.r < i) {
			k = q.back();
			q.pop_back();
		}
		ans[i] = max(ans[i], a[k.x] + sqrt(i - k.x)); //要做两次,所以取max
	}
}
		
int main() {
	n = read();
	for (int i = 1;i <= n; i++) 
		a[i] = read(), ans[i] = a[i];
	work();
	for (int j = 1;j << 1 <= n; j++) 
	swap(a[j], a[n-j+1]), swap(ans[j], ans[n-j+1]);
    //翻转
	while (q.size()) q.pop_front();
	work();
	///*
	for (int i = n;i >= 1; i--)
		printf ("%d\n", int(ceil(ans[i]) - a[i]));
		//*/
	return 0;
}
posted @ 2019-10-05 23:08  Hs-black  阅读(168)  评论(0编辑  收藏  举报