「JOISC 2021 Day2」道路建设
曼哈顿距离与切比雪夫距离转化
曼哈顿距离 \(\longrightarrow\) 切比雪夫距离: \((x,y) \longrightarrow(x+y,x-y)\)
切比雪夫距离 \(\longrightarrow\) 曼哈顿距离: \((x,y) \longrightarrow (\dfrac {x+y} 2,\dfrac {x-y} 2)\)
\(\texttt{Solution:}\)
曼哈顿距离转切比雪夫距离。
二分答案 \(dis\),计算距离 \(\le dis\) 的点对数是否 \(\ge k\)。
这个东西可以先对 \(x\) 排序,然后对于 \(i\),找出 \(j<i\) 并且 \(x_i - x_j \le dis\)的点中有多少个 \(y_j\) 满足 \(y_j \in[y_i - dis,y_i + dis]\)即可。
\(\texttt{Code:}\)
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define ll long long
using namespace std;
const int N = 2.5e5 + 5;
struct st {ll x, y;} p[N];
bool cmp(st a, st b) {return a.x < b.x;}
int n, k;
multiset<ll> S;
multiset<pair<ll, ll> > S2;
vector<ll> ans;
bool chk(ll dis) {
S.clear();
int l = 1, res = k;
for (int i = 1; i <= n; i++) {
while (p[i].x - p[l].x > dis) S.erase(S.find(p[l++].y));
auto it = S.lower_bound(p[i].y - dis);
for (; it != S.end(); it++) {
if (*it > p[i].y + dis) break;
if (--res <= 0) return true;
}
S.insert(p[i].y);
}
return false;
}
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) {
scanf("%lld%lld", &p[i].x, &p[i].y);
p[i].x += p[i].y;
p[i].y = p[i].x - 2 * p[i].y;
}
sort(p + 1, p + n + 1, cmp);
ll l = 0, r = 4e9;
while (l + 1 < r) {
ll mid = (l + r) >> 1;
if (chk(mid)) r = mid;
else l = mid;
}
l = 1;
for (int i = 1; i <= n; i++) {
while (p[i].x - p[l].x > r) S2.erase(S2.find(mp(p[l].y, p[l].x))), l++;
auto it = S2.lower_bound(mp(p[i].y - r, -4e9));
for (; it != S2.end(); it++) {
if (it -> first > p[i].y + r) break;
ans.pb(max(p[i].x - it -> second, (ll)abs(it -> first - p[i].y)));
}
S2.insert(mp(p[i].y, p[i].x));
}
sort(ans.begin(), ans.end());
for (int i = 0; i < k; i++) printf("%lld\n", ans[i]);
return 0;
}
另一道题:\(\texttt{[TJOI2013]松鼠聚会}\)
切比雪夫距离转曼哈顿距离。

浙公网安备 33010602011771号