There are nn towns in Byteland, labeled by 1,2,\dots,n1,2,…,n. The ii-th town's location is (x_i,y_i)(xi,yi). Little Q got a taxi VIP card, he can use the VIP card to cut down the taxi fare. Formally, assume Little Q is at (x',y')(x′,y′), if he calls a taxi to drive him to the kk-th town, the VIP card will reduce \min(|x'-x_k|+|y'-y_k|,w_k)min(∣x′−xk∣+∣y′−yk∣,wk) dollars.
Little Q wants to make full use of his VIP card. He will give you qq queries, in each query you will be given his location, and you need to choose a town such that the VIP card will reduce the most taxi fare.
Input
The first line contains a single integer TT (1 \leq T \leq 1001≤T≤100), the number of test cases. For each test case:
The first line contains two integers nn and qq (1 \leq n,q \leq 100\,0001≤n,q≤100000), denoting the number of towns and the number of queries.
Each of the following nn lines contains three integers x_ixi, y_iyi and w_iwi (1 \leq x_i,y_i,w_i \leq 10^91≤xi,yi,wi≤109), describing a town.
Each of the following qq lines contains two integers x'x′ and y'y′ (1 \leq x',y' \leq 10^91≤x′,y′≤109), describing a query.
It is guaranteed that the sum of all nn is at most 500\,000500000, and the sum of all qq is at most 500\,000500000.
Output
For each query, print a single line containing an integer, denoting the maximum possible reduced taxi fare.
Sample
Input | Output |
---|---|
1 3 4 1 5 7 5 1 6 2 3 9 1 5 2 2 4 3 10 10 | 6 4 5 9 |
题意: 在一个二维平面上有n个点,每个点还具有一个点权wi,q次询问,每次询问给出一个点(x, y),该点到各点的代价为min(两点间曼哈顿距离, wi),求该点到各点代价的最大值。
分析: 在做这道题之前需要知道一个结论,找某点到各点曼哈顿距离最大值只需要看4个点,分别是x+y值最大的点、x-y值最大的点、-x+y值最大的点和-x-y值最大的点,这4点到给定点的曼哈顿距离最大值就是全部点到给定点的曼哈顿距离最大值。设给定点为(x', y'),则证明可以由下图给出:
在知道这个结论后这道题目做起来会稍微简单一些,接下来可以对各点按照权值wi从小到大排序,然后二分点的编号,初始时l = 1,r = n,设dis为[mid, n]中的各点到给定点曼哈顿距离最大值,如果dis >= w[mid],那么[mid, n]中的各点对答案的贡献至少也是w[mid],所以可以用w[mid]更新一下答案,并且可以知道[1, mid-1]中的各点w[i]小于等于w[mid],所以它们不可能再更新答案了,也就不用考虑这些点了,将需要考虑的范围缩小到[mid+1, n],而如果dis < w[mid],那么[mid, n]中的各点对答案的贡献一定是d,所以用d更新一下答案,然后将需要考虑的范围缩小到[1, mid-1]。
具体代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
using namespace std;
struct node{
int x, y, w;
}a[100005];
bool cmp(node x, node y){
return x.w < y.w;
}
int mx1[100005];//记录后i个点的x+y最大点
int mx2[100005];//记录后i个点的x-y最大点
int mx3[100005];//记录后i个点的-x+y最大点
int mx4[100005];//记录后i个点的-x-y最大点
int dis(int t, int x, int y){//dis(t)返回后t个点中曼哈顿距离最大值
int dis1 = abs(a[mx1[t]].x-x)+abs(a[mx1[t]].y-y);
int dis2 = abs(a[mx2[t]].x-x)+abs(a[mx2[t]].y-y);
int dis3 = abs(a[mx3[t]].x-x)+abs(a[mx3[t]].y-y);
int dis4 = abs(a[mx4[t]].x-x)+abs(a[mx4[t]].y-y);
return max(max(dis1, dis2), max(dis3, dis4));
}
signed main()
{
int T;
cin >> T;
while(T--){
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].w);
sort(a+1, a+n+1, cmp);
mx1[n] = mx2[n] = mx3[n] = mx4[n] = n;
for(int i = n-1; i >= 1; i--){
if(a[mx1[i+1]].x+a[mx1[i+1]].y < a[i].x+a[i].y)
mx1[i] = i;
else
mx1[i] = mx1[i+1];
if(a[mx2[i+1]].x-a[mx2[i+1]].y < a[i].x-a[i].y)
mx2[i] = i;
else
mx2[i] = mx2[i+1];
if(-a[mx3[i+1]].x+a[mx3[i+1]].y < -a[i].x+a[i].y)
mx3[i] = i;
else
mx3[i] = mx3[i+1];
if(-a[mx4[i+1]].x-a[mx4[i+1]].y < -a[i].x-a[i].y)
mx4[i] = i;
else
mx4[i] = mx4[i+1];
}
for(int i = 1; i <= m; i++){
int x, y;
scanf("%d%d", &x, &y);
int l = 1, r = n, ans = 0;
while(l <= r){
int mid = l+r>>1;
if(dis(mid, x, y) > a[mid].w){
ans = max(ans, a[mid].w);
l = mid+1;
}
else{
ans = max(ans, dis(mid, x, y));
r = mid-1;
}
}
printf("%d\n", ans);
}
}
return 0;
}