POJ 3667 Hotel ( 线段树区间合并 )

举报
Linux猿 发表于 2021/08/04 23:23:27 2021/08/04
【摘要】 题目链接~~> 做题感悟:这题是接触线段树区间合并的第一题,做的很纠结。 解题思路:                 注意线段树上节点代表的信息 : 每个节点需要维护 lc , rc , mc ,add ,见下图: add 为懒惰标记。假设 i 代表父亲节点编号,左儿子为 &...

题目链接~~>

做题感悟:这题是接触线段树区间合并的第一题,做的很纠结。

解题思路:

                注意线段树上节点代表的信息 : 每个节点需要维护 lc , rc , mc ,add ,见下图:


add 为懒惰标记。假设 i 代表父亲节点编号,左儿子为  i * 2  ,右儿子为 i * 2  + 1 ,那么我们可以得到 : T [ i ] .lc 首先加上左儿子的左边的空格数,然后需要判断一下,如果左儿子的左节点占满了整个左区间时需要再加上右儿子的左边的空格数。同理 T [ i ] .rc 也可以这样得到。那么 mc 怎样维护呢 ? 无非是左儿子的 mc  ,右儿子的 mc .不要忘记左儿子的右区间 + 右儿子的左区间也可以。这样就可以了。

代码:


  
  1. #include<iostream>
  2. #include<sstream>
  3. #include<map>
  4. #include<cmath>
  5. #include<fstream>
  6. #include<queue>
  7. #include<vector>
  8. #include<sstream>
  9. #include<cstring>
  10. #include<cstdio>
  11. #include<stack>
  12. #include<bitset>
  13. #include<ctime>
  14. #include<string>
  15. #include<cctype>
  16. #include<iomanip>
  17. #include<algorithm>
  18. using namespace std ;
  19. #define INT __int64
  20. #define L(x) (x * 2)
  21. #define R(x) (x * 2 + 1)
  22. const int INF = 0x3f3f3f3f ;
  23. const double esp = 0.0000000001 ;
  24. const double PI = acos(-1.0) ;
  25. const int mod = 1000000007 ;
  26. const int MY = (1<<5) + 5 ;
  27. const int MX = 50000 + 5 ;
  28. const int S = 20 ;
  29. int n ,m ;
  30. struct node
  31. {
  32. int le ,rt ,add ;
  33. int lc ,rc ,mc ;
  34. }T[MX<<2] ;
  35. void build(int i ,int le ,int rt) // 建树
  36. {
  37. T[i].le = le ;
  38. T[i].rt = rt ;
  39. T[i].add = -1 ;
  40. T[i].lc = T[i].rc = T[i].mc = rt - le + 1 ;
  41. if(le == rt) return ;
  42. int Mid = (le + rt)>>1 ;
  43. build(L(i) ,le ,Mid) ;
  44. build(R(i) ,Mid+1 ,rt) ;
  45. }
  46. void push_down(int i) // 向下更新
  47. {
  48. if(T[i].add != -1)
  49. {
  50. int Mid = (T[i].rt + T[i].le)>>1 ;
  51. T[L(i)].add = T[R(i)].add = T[i].add ;
  52. T[L(i)].lc = T[L(i)].rc = T[L(i)].mc = T[i].add ? 0 : (Mid - T[i].le + 1) ;
  53. T[R(i)].lc = T[R(i)].rc = T[R(i)].mc = T[i].add ? 0 : (T[i].rt - Mid) ;
  54. T[i].add = -1 ;
  55. }
  56. }
  57. void push_up(int i) // 向上回溯
  58. {
  59. T[i].lc = T[L(i)].lc ;
  60. T[i].rc = T[R(i)].rc ;
  61. if(T[L(i)].lc == T[L(i)].rt - T[L(i)].le + 1) //
  62. T[i].lc += T[R(i)].lc ;
  63. if(T[R(i)].rc == T[R(i)].rt - T[R(i)].le + 1)
  64. T[i].rc += T[L(i)].rc ;
  65. T[i].mc = max(max(T[L(i)].mc ,T[R(i)].mc) ,T[L(i)].rc + T[R(i)].lc) ;
  66. }
  67. void section(int i ,int le ,int rt ,int add) // 区间更新
  68. {
  69. if(T[i].le == le && T[i].rt == rt)
  70. {
  71. T[i].add = add ;
  72. T[i].lc = T[i].rc = T[i].mc = add ? 0 : (T[i].rt - T[i].le + 1) ;
  73. return ;
  74. }
  75. push_down(i) ;
  76. int Mid = (T[i].le + T[i].rt)>>1 ;
  77. if(le > Mid) section(R(i) ,le ,rt ,add) ;
  78. else if(rt <= Mid) section(L(i) ,le ,rt ,add) ;
  79. else
  80. {
  81. section(L(i) ,le ,Mid ,add) ;
  82. section(R(i) ,Mid+1 ,rt ,add) ;
  83. }
  84. push_up(i) ;
  85. }
  86. int Query(int i ,int Len) // 查询最左边的编号
  87. {
  88. if(T[i].le == T[i].rt)
  89. return 1 ;
  90. push_down(i) ;
  91. int Mid = (T[i].le + T[i].rt)>>1 ;
  92. if(T[L(i)].mc >= Len) // 进入左区间
  93. return Query(L(i) ,Len) ;
  94. else if(T[L(i)].rc + T[R(i)].lc >= Len)
  95. return Mid - T[L(i)].rc + 1 ;
  96. else
  97. return Query(R(i) ,Len) ;
  98. }
  99. int main()
  100. {
  101. //freopen("input.txt" ,"r" ,stdin) ;
  102. int pos ,x ,L ;
  103. while(~scanf("%d%d" ,&n ,&m))
  104. {
  105. build(1 ,1 ,n) ;
  106. for(int i = 0 ;i < m ; ++i)
  107. {
  108. scanf("%d" ,&pos) ;
  109. if(pos == 1)
  110. {
  111. scanf("%d" ,&L) ; // 长度
  112. if(T[1].mc < L)
  113. puts("0") ;
  114. else
  115. {
  116. x = Query(1 ,L) ; // 查找最左边的编号
  117. printf("%d\n" ,x) ;
  118. section(1 ,x ,x+L-1 ,1) ; // 占满
  119. }
  120. }
  121. else
  122. {
  123. scanf("%d%d" ,&x ,&L) ; // 清空
  124. section(1 ,x ,x+L-1 ,0) ;
  125. }
  126. }
  127. }
  128. return 0 ;
  129. }


文章来源: blog.csdn.net,作者:Linux猿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nyist_zxp/article/details/41082019

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。