• [好题][曼哈顿距离][二分]Taxi 2022杭电多校第3场 1011


    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

    InputOutput
     
    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]。

    具体代码如下:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. struct node{
    9. int x, y, w;
    10. }a[100005];
    11. bool cmp(node x, node y){
    12. return x.w < y.w;
    13. }
    14. int mx1[100005];//记录后i个点的x+y最大点
    15. int mx2[100005];//记录后i个点的x-y最大点
    16. int mx3[100005];//记录后i个点的-x+y最大点
    17. int mx4[100005];//记录后i个点的-x-y最大点
    18. int dis(int t, int x, int y){//dis(t)返回后t个点中曼哈顿距离最大值
    19. int dis1 = abs(a[mx1[t]].x-x)+abs(a[mx1[t]].y-y);
    20. int dis2 = abs(a[mx2[t]].x-x)+abs(a[mx2[t]].y-y);
    21. int dis3 = abs(a[mx3[t]].x-x)+abs(a[mx3[t]].y-y);
    22. int dis4 = abs(a[mx4[t]].x-x)+abs(a[mx4[t]].y-y);
    23. return max(max(dis1, dis2), max(dis3, dis4));
    24. }
    25. signed main()
    26. {
    27. int T;
    28. cin >> T;
    29. while(T--){
    30. int n, m;
    31. scanf("%d%d", &n, &m);
    32. for(int i = 1; i <= n; i++)
    33. scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].w);
    34. sort(a+1, a+n+1, cmp);
    35. mx1[n] = mx2[n] = mx3[n] = mx4[n] = n;
    36. for(int i = n-1; i >= 1; i--){
    37. if(a[mx1[i+1]].x+a[mx1[i+1]].y < a[i].x+a[i].y)
    38. mx1[i] = i;
    39. else
    40. mx1[i] = mx1[i+1];
    41. if(a[mx2[i+1]].x-a[mx2[i+1]].y < a[i].x-a[i].y)
    42. mx2[i] = i;
    43. else
    44. mx2[i] = mx2[i+1];
    45. if(-a[mx3[i+1]].x+a[mx3[i+1]].y < -a[i].x+a[i].y)
    46. mx3[i] = i;
    47. else
    48. mx3[i] = mx3[i+1];
    49. if(-a[mx4[i+1]].x-a[mx4[i+1]].y < -a[i].x-a[i].y)
    50. mx4[i] = i;
    51. else
    52. mx4[i] = mx4[i+1];
    53. }
    54. for(int i = 1; i <= m; i++){
    55. int x, y;
    56. scanf("%d%d", &x, &y);
    57. int l = 1, r = n, ans = 0;
    58. while(l <= r){
    59. int mid = l+r>>1;
    60. if(dis(mid, x, y) > a[mid].w){
    61. ans = max(ans, a[mid].w);
    62. l = mid+1;
    63. }
    64. else{
    65. ans = max(ans, dis(mid, x, y));
    66. r = mid-1;
    67. }
    68. }
    69. printf("%d\n", ans);
    70. }
    71. }
    72. return 0;
    73. }

  • 相关阅读:
    github常用搜索指令
    火花塞工作原理
    SpringBoot SpringBoot 基础篇 1 快速上手SpringBoot 2 知识加油站 - REST 开发 2.2 入门案例
    GCC各版本对C++的支持情况
    51单片机基础(C语言):定时器时钟
    MyBatis的各种查询功能
    【STL】map容器
    团建游戏----超级明星反串模仿秀
    基于 Spring boot + MyBatis 的在线音乐播放系统
    Linux基础指令
  • 原文地址:https://blog.csdn.net/m0_55982600/article/details/126003153