[关闭]
@Acqua 2018-12-25T08:48:51.000000Z 字数 1989 阅读 1337

POJ3667 Hotel(Dec. 21th, 2018) 区间合并

线段树 未解析

题目

题意

给定一个长度为的房间序列和个操作。
操作1:在房间中选择并占据最靠左的个连续房间。该操作要求输出最左边的房间号,若无法满足则输出0。
操作2:退掉的所有房间。

思路

——来自题解

线段树区间合并,分别用三个线段树数组(亦可写成结构体)维护左边最长区间、右边最长区间、中间最长区间。

反思

  1. 对于变量的命名和辨析一定要到位。
  2. 为了防止重名,需要丰富变量名库。

代码

  1. // La Lune
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. #define N 50005
  7. #define lhijo u << 1
  8. #define rhijo u << 1 | 1
  9. #define root 1, 1, n
  10. #define lson lhijo, l, mid
  11. #define rson rhijo, mid + 1, r
  12. #define morb int u, int l, int r
  13. using namespace std;
  14. int t[N << 2], lu[N << 2], ne[N << 2], oc[N << 2], n, m;
  15. // oc: 占领标记 occupation,-1表示未被操作,0表示被退房,1表示被占领
  16. // t, lu, ne 中的下标都是线段树中下标,lu表示左区间,ne表示右区间,要和以线段树中下标来区分的左儿子、右儿子区别开。
  17. void pushdown(int u, int m){
  18. if(oc[u] != -1){
  19. oc[lhijo] = oc[rhijo] = oc[u]; // 占领标记无差别传递
  20. lu[lhijo] = ne[lhijo] = t[lhijo] = oc[u] ? 0 : (m - (m >> 1));
  21. lu[rhijo] = ne[rhijo] = t[rhijo] = oc[u] ? 0 : (m >> 1);
  22. // 若占领标记为1,则房间数为0,否则为区间长
  23. oc[u] = -1;
  24. }
  25. }
  26. void build(morb){
  27. oc[u] = -1;
  28. t[u] = lu[u] = ne[u] = r - l + 1;
  29. if(l == r) return;
  30. int mid = l + r >> 1;
  31. build(lson);
  32. build(rson);
  33. }
  34. void pushup(int u, int m){
  35. lu[u] = lu[lhijo];
  36. ne[u] = ne[rhijo];
  37. // 根的左区间取左儿子的左区间,右区间取右儿子的右区间
  38. if(lu[u] == m - (m >> 1))
  39. lu[u] += lu[rhijo];
  40. // 若左儿子全空,则左儿子的总区间要与右儿子的左区间合并作为根的左区间
  41. if(ne[u] == m >> 1)// 同理
  42. ne[u] += ne[lhijo];
  43. t[u] = max(ne[lhijo] + lu[rhijo], max(t[lhijo], t[rhijo]));
  44. // 根的中区间从左儿子的中区间、右儿子的中区间、左儿子右区间与右儿子左区间的和中取最大值
  45. }
  46. int query(morb, int w){ // query()返回的是初始房间序号
  47. if(l == r) return 1;
  48. pushdown(u, r - l + 1);
  49. int mid = l + r >> 1;
  50. if(t[lhijo] >= w) // 如果左儿子中区间符合要求,就朝左搜
  51. return query(lson, w);
  52. else if(ne[lhijo] + lu[rhijo] >= w) // 如果中间满足要求,直接返回下标: mid + 1 - 左儿子的右区间ne[lhijo]
  53. return mid - ne[lhijo] + 1;
  54. else
  55. return query(rson, w);
  56. }
  57. void update(morb, int a, int b, int c){
  58. if(a <= l && r <= b){
  59. t[u] = lu[u] = ne[u] = c ? 0 : r - l + 1;
  60. oc[u] = c;
  61. return;
  62. }
  63. pushdown(u, r - l + 1);
  64. int mid = l + r >> 1;
  65. if(a <= mid) update(lson, a, b, c);
  66. if(b > mid) update(rson, a, b, c);
  67. pushup(u, r - l + 1);
  68. }
  69. int main(){
  70. scanf("%d %d", &n, &m);
  71. build(root);
  72. while(m--){
  73. int ctrl, d;
  74. scanf("%d", &ctrl);
  75. if(ctrl == 1){
  76. scanf("%d", &d);
  77. if(t[1] < d){
  78. printf("0\n");
  79. continue;
  80. }
  81. int pos = query(root, d);
  82. update(root, pos, pos + d - 1, 1);
  83. printf("%d\n", pos);
  84. }
  85. else if(ctrl == 2){
  86. int l;
  87. scanf("%d %d", &l, &d);
  88. update(root, l, l + d - 1, 0);
  89. }
  90. else printf("Error.\n");
  91. }
  92. return 0;
  93. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注