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

 

posted @ 2017-07-02 22:45  Galaxies  阅读(155)  评论(0编辑  收藏  举报