bzoj2216 [Poi2011]Lightning Conductor
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2216
【题解】
决策单调性,证明容易,略。
用整体二分的那个trick可以方便实现代码。
复杂度$O(nlogn)$
# include <math.h> # include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e5 + 10; const int mod = 1e9+7; int n, a[M]; ld f[M], g[M]; // p >= aj - ai + sqrt(abs(j-i)) # define abs(x) ((x) > 0 ? (x) : -(x)) inline ld gsum(int i, int j) { return (ld)sqrt(1.0 * abs(j-i)) + a[j]; } inline void solve(int l, int r, int al, int ar, int bl, int br) { if(l > r) return; int mid = l+r>>1; ld mx = -1e18, t; int pos1 = 0, pos2 = 0; for (int i=al; i<=ar && i<=mid; ++i) if((t = gsum(mid, i)) > mx) mx = t, pos1 = i; if(pos1) f[mid] = gsum(mid, pos1); mx = -1e18; for (int i=br; i>=bl && i>=mid; --i) if((t = gsum(mid, i)) > mx) mx = t, pos2 = i; if(pos2) g[mid] = gsum(mid, pos2); solve(l, mid-1, al, pos1, bl, pos2); solve(mid+1, r, pos1, ar, pos2, br); } int main() { cin >> n; for (int i=1; i<=n; ++i) scanf("%d", a+i); solve(1, n, 1, n, 1, n); for (int i=1; i<=n; ++i) printf("%d\n", (int)ceil(max(f[i], g[i]) - a[i])); return 0; }