Official
F - Dist Max 2 Editorial by blackyuki
最小値の最大化は二分探索で解けることが多いです。
まず距離が \(K\) 以上の点のペアが存在するか?という判定問題の解法を考えてみましょう。
- \(\min(|x_i - x_j|, |y_i - y_j|) \geq K \)
を同値変形すると、
- \(|x_i - x_j| \geq K\) かつ \(|y_i - y_j| \geq K\)
となります。よって、距離が \(K\) 以上の点対が存在するための条件は以下の通りです。
ある点 \((x_i,y_i)\) に対して、\(x\) 座標が \(x_i-K\) 以下の点の \(y\) 座標の最小値が \(y_i-K\) 以下または最大値が \(y_i+K\) 以上
これはあらかじめ点を \(x\) 座標でソートしておくことにより、尺取り法を使って \(O(N)\) で判定することができます。
したがって、答えで決め打ち二分探索をすると全体の計算量は \(O(N\log N+N\log \max(x_i))\) となります。
実装例 (C++)
#include <bits/stdc++.h>
using namespace std;
int main(){
int n; cin >> n;
vector<pair<int,int>> v(n);
for(int i = 0; i < n; i++) cin >> v[i].first >> v[i].second;
sort(v.begin(), v.end());
int ok = 0, ng = 1000000001;
while(ng - ok > 1){
int md = (ok + ng)/2;
queue<pair<int,int>> que;
bool able = false;
int mi = 1000000001, ma = 0;
for(auto p:v){
while(!que.empty()){
if(que.front().first > p.first - md)break;
mi = min(mi, que.front().second); ma = max(ma, que.front().second);
que.pop();
}
if(mi <= p.second - md || ma >= p.second + md) able=true;
que.push(p);
}
if(able) ok = md;
else ng = md;
}
cout << ok << endl;
}
posted:
last update: