BZOJ2216【决策单调性】

通过这题学习了决策单调性.顺便学习了wmg_1001【科学】的代码风格.

/* I will wait for you */  
  
#include <cstdio>  
#include <cstdlib>  
#include <cstring>  
#include <cmath>  
#include <ctime>  
#include <algorithm>  
#include <iostream>  
#include <fstream>  
#include <vector>  
#include <queue>  
#include <deque>  
#include <set>  
#include <map>  
#include <string>  
#define make make_pair  
#define fi first  
#define se second  
  
using namespace std;  
  
typedef long long LL;  
typedef unsigned long long ULL;  
typedef pair<int, int> PII;  
  
const int maxn = 500010;  
const int maxm = 1000;  
const int maxs = 100;  
const int INF = 1 << 29;  
const int P = 1000000007;  
const double error = 1e-9;  

inline int read() {
	int x = 0,f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		f = (ch == '-' ? -1 : 1);
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
}
  
struct policy {
	int pos, l, r;
} q[maxn];
  
int n, a[maxn];
double f[maxn], g[maxn];
  
double cal(int x, int y) {
	return a[x] + sqrt(abs(x - y)) - a[y];
}

double fac(int x, int y, int z) {
	return cal(x, z) > cal(y, z);
}

int binary(int x, policy a) {
	int y = a.pos;
	int l = a.l, r = a.r;
	
	while (l <= r) {
		int mid = (l + r) / 2;
		if (fac(x, y ,mid)) r = mid - 1;
		else l = mid + 1;
	}
	
	return l;
}

void dp(double *ans) {
	int head = 1, tail = 0;
	
	for (int i = 0; i < n; i++) {
		q[head].l++;
		if (head <= tail && q[head].l > q[head].r) head++;
		
		if (head > tail || fac(i, q[head].pos, n - 1)) {
			
			while (head <= tail && fac(i, q[tail].pos, q[tail].l)) tail--;
			
			if (head > tail) q[++tail] = (policy) {i, i, n};
			
			else {
				int mid = binary(i, q[tail]);
				q[tail].r = mid - 1;
				q[++tail] = (policy) {i, mid, n};
			}
		}
		
		ans[i] = max(ans[i], cal(q[head].pos, i));
	}
}

int main() {  
	n = read();
	for (int i = 0; i < n; i++) a[i] = read();
	
	dp(f);
	for (int i = 0; i < n / 2; i++) swap(a[i], a[n - i - 1]);
	dp(g);

	for (int i = 0; i < n; i++) {
		double ans = max(f[i], g[n - i - 1]);
		ans = max(ans, 0.0);
		printf("%d\n", (int) ceil(ans));
	}
	
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值