1. 程式人生 > 其它 >ABC215 F - Dist Max 2(二分答案)

ABC215 F - Dist Max 2(二分答案)

目錄

Description

\(n\) 個點,每個點之間的距離為 \(min(|x_i-x_j|,|y_i-y_j|)\),求點與點之間的最大值

State

\(2<=n<=2*10^5\)

\(0<=x_i,y_i<=10^9\)

Input

3
0 3
3 1
4 10

Output

4

Solution

題目還是很巧妙地,知道了用二分就已經解決一半了

由於兩點之間的距離 \(min(|x_i-x_j|,|y_i-y_j|)\),所以如果橫座標兩點的距離確定後,那麼可以排除很多點,只留下 \(|y_i-y_j|<|x_i-x_j|\) 的那些 \(j\)

上面的思路提供了一個突破點:距離;

將橫座標升序排列,二分距離記為 \(x\),如果存在 \(j\) 使得 \(|x_j-x_i|>=x\),(\([j,n]\) 上的點都會滿足),之後如果有 \(|y_k-y_i|>=x\)\(k∈[j,n]\)),則 \(x\) 可以被確定為答案


Code

const int N = 1e6 + 5;
 
    int n, m, k, _;
    pll a[N];
    ll maxx[N];
    ll minn[N];

bool check(ll x)
{
    int p = 1;
    for(int i = 1; i <= n;){
        if(a[i].fi - a[p].fi >= x){
            if(maxx[i] - a[p].se >= x) return 1;
            if(a[p].se - minn[i] >= x) return 1;
            p ++;
        }
        else i ++;
    }
    return 0;
}

signed main()
{
    //IOS;
    while(~ sd(n)){
        rep(i, 1, n){
            sll2(a[i].fi, a[i].se);
        }
        sort(a + 1, a + 1 + n);
        maxx[n] = minn[n] = a[n].se;
        for(int i = n - 1; i; i --){
            maxx[i] = max(maxx[i + 1], a[i].se);
            minn[i] = min(minn[i + 1], a[i].se);
        }
        ll l = 0, r = 2e9, ans = 0;
        while(r >= l){
            ll mid = l + r >> 1;
            if(check(mid)){
                ans = mid;
                l = mid + 1;
            } 
            else{
                r = mid - 1;
            }
        }
        pll(ans);
    }
    //PAUSE;
    return 0;
}