K - Taxi
题意
开始给你n个点 每个点的坐标\((x_i,y_i)\),权值\(w_i\),一共q次询问, 每次询问给你一个点(qx, qy),求该点到前面某个点的距离的最大值是多少。
两个点之间的距离定义为\(min(|x - xi| + |y - yi|, wi)\)。
思路
我们可以O(1)地求出集合外一点到该集合中的某一个点的最大曼哈顿距离。
\[max(abs(qx - x) + abs(qy - y)) = max(qx-x+qy-y, qx-x+y-qy, x-qx+qy-y, x-qx+y-qy) = max((qx+qy)-(x+y), (x+y)-(qx+qy), (qx-qy)-(x-y), (x-y)-(qx-qy)) = max(|(qx+qy) - (x+y)|, |(qx-qy) - (x-y)|)\]维护区间的\(mx_x+y, mi_x+y, mx_x-y, mi_x-y\)即可求得区间最大曼哈顿距离
然后我们将点按权值从大到小排
然后二分城市 对于某个点x 比较x及以后的最大曼哈顿距离d,如果d>x.w说明x即以后的区间可以找到比x.w大的更优解, 我们就再向右二分。
如果d<x.w,那么说明x及以后找不到比x.w小的更优解那么我们先记录这段的最大曼哈顿距离(\(ans=max(ans,d)\))然后往左找更优解。
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int N = 1e5 + 10;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int n, q, mi1[N], mx1[N], mi2[N], mx2[N], ans;
pair<int, pair<int, int>>p[N];
bool check(int id, int x, int y) {
int d = max(abs(x + y - mi1[id]), abs(x + y - mx1[id]));
d = max({ d, abs(x - y - mi2[id]), abs(x - y - mx2[id]) });
if (d >= p[id].first) return true;
ans = max(ans, d);
return false;
}
void solve()
{
cin >> n >> q;
for (int i = 1, x, y, w; i <= n; i++) {
cin >> x >> y >> w;
p[i] = { w, {x, y} };
}
sort(p + 1, p + 1 + n);
mi1[n] = mx1[n] = p[n].second.first + p[n].second.second;
mi2[n] = mx2[n] = p[n].second.first - p[n].second.second;
for (int i = n - 1; i >= 1; i--) {
mi1[i] = min(mi1[i + 1], p[i].second.first + p[i].second.second);
mx1[i] = max(mx1[i + 1], p[i].second.first + p[i].second.second);
mi2[i] = min(mi2[i + 1], p[i].second.first - p[i].second.second);
mx2[i] = max(mx2[i + 1], p[i].second.first - p[i].second.second);
}
for (int i = 1, x, y; i <= q; i++) {
cin >> x >> y;
ans = min(p[1].first, abs(x - p[1].second.first) + abs(y - p[1].second.second));
int l = 1, r = n;
while (l <= r) {
int mid = (l + r) / 2;
if (check(mid, x, y)) {
ans = max(ans, min(p[mid].first, abs(x - p[mid].second.first) + abs(y - p[mid].second.second)));
l = mid + 1;
}
else r = mid - 1;
}
cout << ans << "\n";
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int _t = 1;
cin >> _t;
while (_t--)
solve();
return 0;
}
标签:Taxi,qy,qx,int,second,2022,max,杭电杯,first
From: https://www.cnblogs.com/yaqu-qxyq/p/16740082.html