参考:http://www.cnblogs.com/slon/archive/2012/03/30/2426104.html

题意:给一个有n个点的点集,有q个询问,每个询问询问一个点p,求与p曼哈顿距离最小的点,并输出曼哈顿距离的最小值。

分析:使得abs(qx - xi) + abs(qy - yi)最小,因为带了个绝对值,所以没法直接套用一些数据结构中查询最值的操作,一时间也没什么头绪。后来看到上面的博客,才明白可以分情况讨论,把绝对值去掉。

一共四种情况:

qx >= xi && qy >= yi

qx >= xi && qy <= yi

qx <= xi && qy >= yi

qx <= xi && qy <= yi

以第一种情况为例分析,其他三种情况分析方法相同。

当 qx > xi && qy > yi 时,直接去绝对值得到:qx - xi + qy - yi = ( qx + qy ) - ( xi +yi ),因为对于每个查询qx + qy相当于一个常数,所以若使qx - xi + qy - yi最小,则 (xi + yi) 最大即可。

于是就转换成了单点更新+区间查最值问题。

线段树离线处理:将点集和查询一块考虑,按上述四种情况分别对点排序,x为第一优先级,y为第二优先级。

将y坐标离散化。

对于每个询问,查询其所属的区间中的最大值。

PS1.其实不用搞四次的,不过这样比较好理解……

PS2.sort函数要仔细考虑一下,跟循环正着跑还是倒着跑有关,之前这里没考虑清楚,样例都跑不对。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cstdlib>
  4. #include <algorithm>
  5.  
  6. #define LL long long int
  7. #define lson l, m, rt << 1
  8. #define rson m + 1, r, rt << 1 | 1
  9.  
  10. using namespace std;
  11.  
  12. const int MAXN = + ;
  13. const LL INF = 1LL << ;
  14.  
  15. struct node
  16. {
  17. LL x, y;
  18. int id;
  19. void readNode()
  20. {
  21. scanf( "%I64d%I64d", &x, &y );
  22. return;
  23. }
  24. };
  25.  
  26. bool cmp1( node a, node b )
  27. {
  28. if ( a.x != b.x ) return a.x < b.x;
  29. if ( a.y != b.y ) return a.y < b.y;
  30. return a.id < b.id;
  31. }
  32.  
  33. bool cmp2( node a, node b )
  34. {
  35. if ( a.x != b.x ) return b.x < a.x;
  36. if ( a.y != b.y ) return a.y < b.y;
  37. return b.id < a.id;
  38. }
  39.  
  40. bool cmp3( node a, node b )
  41. {
  42. if ( a.x != b.x ) return b.x < a.x;
  43. if ( a.y != b.y ) return a.y < b.y;
  44. return a.id < b.id;
  45. }
  46.  
  47. bool cmp4( node a, node b )
  48. {
  49. if ( a.x != b.x ) return a.x < b.x;
  50. if ( a.y != b.y ) return a.y < b.y;
  51. return b.id < a.id;
  52. }
  53.  
  54. int N, Q;
  55. int all, cntY;
  56. node D[MAXN];
  57. LL maxi[ MAXN << ];
  58. LL ans[MAXN];
  59. LL hashY[MAXN];
  60.  
  61. void build( int l, int r, int rt )
  62. {
  63. maxi[rt] = -INF;
  64. if ( l == r ) return;
  65. int m = ( l + r ) >> ;
  66. build( lson );
  67. build( rson );
  68. return;
  69. }
  70.  
  71. void PushUp( int rt )
  72. {
  73. maxi[rt] = max( maxi[rt << ], maxi[rt << | ] );
  74. }
  75.  
  76. void update( LL val, int pos, int l, int r, int rt )
  77. {
  78. if ( l == pos && r == pos )
  79. {
  80. maxi[rt] = max( maxi[rt], val );
  81. return;
  82. }
  83. int m = ( l + r ) >> ;
  84. if ( pos <= m ) update( val, pos, lson );
  85. else update( val, pos, rson );
  86. PushUp( rt );
  87. return;
  88. }
  89.  
  90. LL query( int L, int R, int l, int r, int rt )
  91. {
  92. if ( L <= l && r <= R )
  93. {
  94. return maxi[rt];
  95. }
  96.  
  97. LL res = -INF;
  98. int m = ( l + r ) >> ;
  99. if ( L <= m ) res = max( res, query( L, R, lson ) );
  100. if ( R > m ) res = max( res, query( L, R, rson ) );
  101. return res;
  102. }
  103.  
  104. void init()
  105. {
  106. for ( int i = ; i < N; ++i )
  107. {
  108. D[i].readNode();
  109. D[i].id = -;
  110. hashY[i] = D[i].y;
  111. }
  112. scanf( "%d", &Q );
  113. for ( int i = ; i < Q; ++i )
  114. {
  115. D[ N + i ].readNode();
  116. D[ N + i ].id = i;
  117. hashY[ N + i ] = D[N + i].y;
  118. ans[i] = INF;
  119. }
  120.  
  121. all = N + Q;
  122. sort( hashY, hashY + all );
  123. cntY = unique( hashY, hashY + all ) - hashY;
  124. return;
  125. }
  126.  
  127. int main()
  128. {int cas = ;
  129. while ( scanf( "%d", &N ), N != - )
  130. {
  131. init();
  132. build( , cntY, );
  133. sort( D, D + all, cmp1 );
  134.  
  135. for ( int i = ; i < all; ++i )
  136. {
  137. int id = lower_bound( hashY, hashY + cntY, D[i].y ) - hashY;
  138. ++id;
  139. if ( D[i].id == - ) update( D[i].x + D[i].y, id, , cntY, );
  140. else
  141. {
  142. ans[ D[i].id ] = min( ans[ D[i].id ], D[i].x + D[i].y - query( , id, , cntY, ) );
  143. }
  144. }
  145.  
  146. build( , cntY, );
  147. sort( D, D + all, cmp2 );
  148. for ( int i = all - ; i >= ; --i )
  149. {
  150. int id = lower_bound( hashY, hashY + cntY, D[i].y ) - hashY;
  151. ++id;
  152. if ( D[i].id == - ) update( D[i].x - D[i].y, id, , cntY, );
  153. else
  154. {
  155. ans[ D[i].id ] = min( ans[ D[i].id ], D[i].x - D[i].y - query( id, cntY, , cntY, ) );
  156. }
  157. }
  158.  
  159. build( , cntY, );
  160. sort( D, D + all, cmp3 );
  161. for ( int i = ; i < all; ++i )
  162. {
  163. int id = lower_bound( hashY, hashY + cntY, D[i].y ) - hashY;
  164. ++id;
  165. if ( D[i].id == - ) update( D[i].y - D[i].x, id, , cntY, );
  166. else
  167. {
  168. ans[ D[i].id ] = min( ans[ D[i].id ], D[i].y - D[i].x - query( , id, , cntY, ) );
  169. }
  170. }
  171.  
  172. build( , cntY, );
  173. sort( D, D + all, cmp4 );
  174. for ( int i = all - ; i >= ; --i )
  175. {
  176. int id = lower_bound( hashY, hashY + cntY, D[i].y ) - hashY;
  177. ++id;
  178. if ( D[i].id == - ) update( -D[i].x - D[i].y, id, , cntY, );
  179. else
  180. {
  181. ans[ D[i].id ] = min( ans[ D[i].id ], -D[i].x - D[i].y - query( id, cntY, , cntY, ) );
  182. }
  183. }
  184.  
  185. if ( cas ) puts("");
  186. for ( int i = ; i < Q; ++i )
  187. printf( "%I64d\n", ans[i] );
  188. ++cas;
  189. }
  190. return ;
  191. }

HDU 4189 Cybercrime Donut Investigation 线段树+思路的更多相关文章

  1. HDU 3016 Man Down (线段树+dp)

    HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  2. HDU.5692 Snacks ( DFS序 线段树维护最大值 )

    HDU.5692 Snacks ( DFS序 线段树维护最大值 ) 题意分析 给出一颗树,节点标号为0-n,每个节点有一定权值,并且规定0号为根节点.有两种操作:操作一为询问,给出一个节点x,求从0号 ...

  3. HDU.1556 Color the ball (线段树 区间更新 单点查询)

    HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...

  4. HDU.1166 敌兵布阵 (线段树 单点更新 区间查询)

    HDU.1166 敌兵布阵 (线段树 单点更新 区间查询) 题意分析 加深理解,重写一遍 代码总览 #include <bits/stdc++.h> #define nmax 100000 ...

  5. HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)

    HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...

  6. HDU.1689 Just a Hook (线段树 区间替换 区间总和)

    HDU.1689 Just a Hook (线段树 区间替换 区间总和) 题意分析 一开始叶子节点均为1,操作为将[L,R]区间全部替换成C,求总区间[1,N]和 线段树维护区间和 . 建树的时候初始 ...

  7. hdu 1754 I Hate It 线段树 点改动

    // hdu 1754 I Hate It 线段树 点改动 // // 不多说,裸的点改动 // // 继续练 #include <algorithm> #include <bits ...

  8. hdu 1166 敌兵布阵 线段树 点更新

    // hdu 1166 敌兵布阵 线段树 点更新 // // 这道题裸的线段树的点更新,直接写就能够了 // // 一直以来想要进线段树的坑,结果一直没有跳进去,今天算是跳进去吧, // 尽管十分简单 ...

  9. R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数

    R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...

随机推荐

  1. Hive 常用命令和语句

    示例数据库为 db_hive 1. 创建表 create-table.sql create table if not exists db_hive.tb_user ( id int, username ...

  2. Can Microsoft’s exFAT file system bridge the gap between OSes?

    转自:http://arstechnica.com/information-technology/2013/06/review-is-microsofts-new-data-sharing-syste ...

  3. 08_1_IO

    08_1_IO 1. 输入/输出流的分类 java.io包中定义了多个流类型(类或抽象类)来实现输入/输出功能:可以从不同的角度对其进行分类: 按数据流的方向不同可以分给输入流和输出流. 按处理数据单 ...

  4. Objective-c 单例设计模式

    Objective-c 单例设计模式 一.什么是单例模式:(Singleton)      单例模式的意图是是的类的对象成为系统中唯一的实例,提供一个访问点,供客户类共享资源.   二.什么情况下使用 ...

  5. 【iOS】史上最全的iOS持续集成教程 (下)

    :first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdow ...

  6. egg的使用方法

    1.controller const {ctx,service} = this: let id = ctx.query.id // 获取GET的参数 let body = ctx.request.bo ...

  7. tomcat日志切割脚本

    tomcat日志每俩小时切割的脚本如下(这是用定时任务来完成的,此方法无需重启tomcat): time=$(date +%H) end_time=`` a=$end_time BF_TIME=$(- ...

  8. 前端性能优化JavaScript篇

    关于前端性能优化的讨论一直都很多,包罗的知识也很多,可以说性能优化只有更好,没有最好.前面我写了一篇关于css优化的总结文章,今天再从javascript方面聊一聊. 1.从资源加载方面来说,浏览器的 ...

  9. 访问远程mysql数据库,出现报错,显示“1130 - Host'xxx.xxx.xxx.xxx' is not allowed to connect to this MySQL server“

    在使用Navicat for MySQl访问远程mysql数据库,出现报错,显示“1130 - Host'xxx.xxx.xxx.xxx' is not allowed to connect to t ...

  10. 易语言制作的QQ聊天中常用的GIF图片【带源码下载】

    该软件调用网页实现表情包制作,使用了精益模块. 最近比较火的王境泽.张学友.切格瓦拉.为所欲为.今天星期五.黑人问号脸.偷电瓶车.诸葛孔明.金坷垃等都可以通过此软件在线制作属于你的表情包. 太困了懒得 ...