题意:一个老鼠在一条长度为L的直线上跑,吃蛋糕,老鼠只能沿直线移动。开始时没有蛋糕,老鼠的初始位置是0.

有两个操作,0 x 代表在位置x添加一个蛋糕; 1 代表老鼠想吃蛋糕。老鼠每次都会选择离自己最近的点,如果两边距离相同,老鼠优先选择与自己当前移动方向相同的点。

求最终移动的总距离。

题解:线段树单点修改+查询区间端点。

设当前位置为pos,每次查询区间[0, pos]的最右端和区间[pos, L]的最左端,比较选择哪个更近。

详细题解见代码注释。

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <cmath>
  6.  
  7. #define lson l, m, rt << 1
  8. #define rson m+1, r, rt << 1 | 1
  9.  
  10. #define LEFT 0
  11. #define RIGHT 1
  12.  
  13. using std::min;
  14. using std::max;
  15. using std::abs;
  16.  
  17. const int MAXN = ;
  18. const int INF = << ;
  19.  
  20. int tr[MAXN << ]; //标记哪个点有蛋糕
  21. int left[MAXN << ]; //标记区间[l, r]内有蛋糕的最左端点
  22. int right[MAXN << ]; //标记区间[l, r]内有蛋糕的最右端点
  23. int N, S;
  24. int findL, findR; //标记查找到的任意区间[l, r]中有蛋糕的最左端和最右端
  25.  
  26. void PushUp( int rt )
  27. {
  28. int lc = rt << ;
  29. int rc = rt << | ;
  30. left[rt] = min( left[lc], left[rc] );
  31. right[rt] = max( right[lc], right[rc] );
  32. return;
  33. }
  34.  
  35. void build( int l, int r, int rt ) //建树
  36. {
  37. tr[rt] = ; //每个点初始蛋糕数目为0
  38. left[rt] = INF;
  39. right[rt] = -INF;
  40. if ( l == r ) return;
  41. int m = ( l + r ) >> ;
  42. build( lson );
  43. build( rson );
  44. return;
  45. }
  46.  
  47. void Update( int pos, int v, int l, int r, int rt ) //更新
  48. {
  49. if ( l == pos && r == pos )
  50. {
  51. tr[rt] += v; //更新该点的蛋糕数目
  52. if ( tr[rt] == ) //如果这一点没有蛋糕了
  53. {
  54. left[rt] = INF;
  55. right[rt] = -INF;
  56. }
  57. else //如果这一点有蛋糕
  58. {
  59. left[rt] = l;
  60. right[rt] = l;
  61. }
  62. return;
  63. }
  64.  
  65. int m = ( l + r ) >> ;
  66. if ( pos <= m ) Update( pos, v, lson );
  67. else Update( pos, v, rson );
  68. PushUp( rt );
  69. return;
  70. }
  71.  
  72. void Query( int L, int R, int l, int r, int rt ) //查询
  73. {
  74. if ( L <= l && r <= R )
  75. {
  76. findL = min( left[rt], findL );
  77. findR = max( right[rt], findR );
  78. return;
  79. }
  80. int m = ( l + r ) >> ;
  81. if ( L <= m ) Query( L, R, lson );
  82. if ( R > m ) Query( L, R, rson );
  83. return;
  84. }
  85.  
  86. int main()
  87. {
  88. int T, cas = ;
  89. scanf( "%d", &T );
  90. while ( T-- )
  91. {
  92. scanf( "%d%d", &N, &S );
  93. ++N; //原题目中pipe长度为L,编号为0-L,实际上是有(L+1)个点,
  94. //之前没注意,RE了一次,在这里我把每个点编号为1-(L+1)
  95.  
  96. int curPos = ; //当前位置
  97. int curDirection = RIGHT; //当前方向
  98. int sum = ; //移动总路程
  99.  
  100. build( , N, ); //建树
  101.  
  102. while ( S-- )
  103. {
  104. //printf("**************curPos=%d curDir=%d\n", curPos, curDirection );
  105. int op, pos;
  106. scanf( "%d", &op );
  107. if ( op == )
  108. {
  109. scanf( "%d", &pos );
  110. Update( pos+, , , N, );
  111. }
  112. else
  113. {
  114. bool find = false;
  115. int findpos;
  116.  
  117. if ( curDirection == LEFT ) //如果当前方向向左
  118. {
  119. int LL, RR;
  120. findL = INF;
  121. findR = -INF;
  122. Query( , curPos, , N, ), LL = findR; //向左走,找离当前点最近的右端点
  123. findL = INF;
  124. findR = -INF;
  125. Query( curPos, N, , N, ), RR = findL; //向右走,找离当前点最近的左端点
  126.  
  127. if ( LL == -INF && RR == INF ) //两边都没有蛋糕
  128. {
  129. find = false;
  130. }
  131. else if ( LL == -INF && RR != INF ) //只有右边有蛋糕
  132. {
  133. find = true;
  134. findpos = RR;
  135. curDirection = RIGHT;
  136. }
  137. else if ( LL != -INF && RR == INF ) //只有左边有蛋糕
  138. {
  139. find = true;
  140. findpos = LL;
  141. curDirection = LEFT;
  142. }
  143. else //两边都有蛋糕
  144. {
  145. find = true;
  146. if ( curPos - LL <= RR - curPos ) //注意等号,两边距离相等时优先选择左边
  147. {
  148. findpos = LL;
  149. curDirection = LEFT;
  150. }
  151. else
  152. {
  153. findpos = RR;
  154. curDirection = RIGHT;
  155. }
  156. }
  157.  
  158. //printf("LEFT: ");
  159. }
  160. else
  161. {
  162. int LL, RR;
  163. findL = INF;
  164. findR = -INF;
  165. Query( curPos, N, , N, ), RR = findL;
  166. findL = INF;
  167. findR = -INF;
  168. Query( , curPos, , N, ), LL = findR;
  169.  
  170. if ( LL == -INF && RR == INF )
  171. {
  172. find = false;
  173. }
  174. else if ( LL == -INF && RR != INF )
  175. {
  176. find = true;
  177. findpos = RR;
  178. curDirection = RIGHT;
  179. }
  180. else if ( LL != -INF && RR == INF )
  181. {
  182. find = true;
  183. findpos = LL;
  184. curDirection = LEFT;
  185. }
  186. else
  187. {
  188. find = true;
  189. if ( curPos - LL < RR - curPos ) //注意没有等号,两边距离相等时优先选择右边
  190. {
  191. findpos = LL;
  192. curDirection = LEFT;
  193. }
  194. else
  195. {
  196. findpos = RR;
  197. curDirection = RIGHT;
  198. }
  199. }
  200.  
  201. //printf("RIGHT: ");
  202. }
  203. //printf( "findL=%d findR=%d\n", findL, findR );
  204.  
  205. //printf( "findpos = %d\n", findpos );
  206. if ( find )
  207. {
  208. sum += abs( findpos - curPos );
  209. curPos = findpos;
  210. Update( findpos, -, , N, );
  211. }
  212. }
  213. }
  214.  
  215. printf( "Case %d: %d\n", ++cas, sum );
  216. }
  217. return ;
  218. }

HDU 4302 Holedox Eating (线段树模拟)的更多相关文章

  1. HDU 4302 Holedox Eating (STL + 模拟)

    Holedox Eating Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  2. hdu 4302 Holedox Eating(优先队列/线段树)

    题意:一只蚂蚁位与原点,在x轴正半轴上会不时地出现一些蛋糕,蚂蚁每次想吃蛋糕时选取最近的去吃,如果前后距离相同,则吃眼前的那一块(即方向为蚂蚁的正前),求最后蚂蚁行进距离. 思路:优先队列q存储蚂蚁前 ...

  3. hdu 4302 Holedox Eating

    http://acm.hdu.edu.cn/showproblem.php?pid=4302 #include <cstdio> #include <cstring> #inc ...

  4. HDU 4302 Holedox Eating(multiset)

    http://acm.hdu.edu.cn/showproblem.php?pid=4302 题意: 在一条直线上,会有多条命令,如果是0,那么就会在x位置处出现一个蛋糕,如果是1,某人就会找到最近的 ...

  5. hdu_5818_Joint Stacks(线段树模拟)

    题目链接:hdu_5818_Joint Stacks 题意: 给你两个栈,多了个合并操作,然后让你模拟 题解: 很容易想到O(1)的单个栈操作,O(n)的合并操作,这样肯定超时,所以我们要将时间复杂度 ...

  6. hdu 5700区间交(线段树)

    区间交 Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  7. 【CF280D】 k-Maximum Subsequence Sum ,线段树模拟费用流

    昨天考试被教育了一波.为了学习一下\(T3\)的科技,我就找到了这个远古时期的\(cf\)题(虽然最后\(T3\)还是不会写吧\(QAQ\)) 顾名思义,这个题目其实可以建成一个费用流的模型.我们用流 ...

  8. 2019牛客暑期多校训练营(第八场)E:Explorer(LCT裸题 也可用线段树模拟并查集维护连通性)

    题意:给定N,M,然后给出M组信息(u,v,l,r),表示u到v有[l,r]范围的通行证有效.问有多少种通行证可以使得1和N连通. 思路:和bzoj魔法森林有点像,LCT维护最小生成树.  开始和队友 ...

  9. Snacks HDU 5692 dfs序列+线段树

    Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...

随机推荐

  1. MySQL(mariadb)多实例应用与多实例主从复制

    MySQL多实例 mysql多实例,简单理解就是在一台服务器上,mysql服务开启多个不同的端口(如3306.3307,3308),运行多个服务进程.这些 mysql 服务进程通过不同的 socket ...

  2. linux系统可执行文件添加环境变量使其跨终端和目录执行

    在命令行终端输入:echo $PATH 回车可打印出PATH变量对应的路径 现有一可执行文件qtFirstC,文件所在目录为:/home/lolors/qtFirstC 此时test只能在此目录下运行 ...

  3. 编写radware的负载配置

    radware如何添加负载服务? 笔者在新添加radware的新负载服务的时候,是习惯去看下上一个负载服务的ID 和 节点服务的ID 号 分别是多少,主要是避免ID冲突,把其他服务顶替下去,同时以后这 ...

  4. git 完善使用中

    GIT 版本库控制: 第一步:Git 的账号注册 url :https://github.com/ 这是git的官网如果第一次打开会这样 中间红色圈内是注册 内容, 第一项是用户名 第二项是邮箱 第三 ...

  5. opencv移植(二)

    原文:https://blog.csdn.net/Guet_Kite/article/details/78667175?utm_source=copy 版权声明:本文为博主原创文章,转载请附上博文链接 ...

  6. 定义一个大数组时,出现错误,程序进入HardFault_Handler中断

    在原子的串口程序前加了几个数组定义,加了个对数组处理的函数,出现了HardFault_Handler的错误,不知道怎么解决!!! 因为局部变量是存放在栈区的,而全局变量在全局区(静态区),如果栈区较小 ...

  7. 10-第三方ClientCredential模式调用

    1-新建.net core控制台应用程序 E:\coding\netcore\IdentityServerSample>dotnet new console --name ThridPartDe ...

  8. java的编码格式

    几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言 ...

  9. 20145202马超《java》实验四

    实验指导:http://www.cnblogs.com/lxm20145215----/p/5444207.html 实验指导:http://www.cnblogs.com/Vivian517/p/6 ...

  10. MapWinGIS使用

    .net语言中使用MapWinGIS.ocx http://www.cnblogs.com/kekec/archive/2011/03/30/1999709.html 基于MapWinGis的开发探索 ...