「JOISC 2021 Day2」道路建设

曼哈顿距离与切比雪夫距离转化

曼哈顿距离 \(\longrightarrow\) 切比雪夫距离: \((x,y) \longrightarrow(x+y,x-y)\)

切比雪夫距离 \(\longrightarrow\) 曼哈顿距离: \((x,y) \longrightarrow (\dfrac {x+y} 2,\dfrac {x-y} 2)\)

\(\texttt{本题题面}\)

\(\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]松鼠聚会}\)

切比雪夫距离转曼哈顿距离。

posted @ 2021-10-15 10:07  klii  阅读(107)  评论(0)    收藏  举报