1. 程式人生 > >BZOJ2216【決策單調性】

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;
}