Poj 3667 - Hotel 线段树--区间合并

最近一直在看胡浩的【完全版】线段树,这个题目是在他的blog介绍的

 

文字没有参考别人的成分

 

题目大意:Hotel有N(1 ≤ N ≤ 50,000)间rooms,并且所有的rooms都是连续排列在同一边,groups需要check in 房间,要求房间的编号为连续的r..r+Di-1并且r是最小的;visitors同样可能check out,并且他们每次check out都是编号为Xi ..Xi +Di-1 (1 ≤ XiN-Di+1)的房间,题目的输入有两种样式:

  1. 1  a     :  groups需要check in  a间编号连续的房间
  2. 2  a   b : visitors  check out 房间,其中房间编号是 a…a+b-1

要求对于每次request,输出为groups分配数目为a的房间中编号最小的房间编号

 

思路:利用线段树建立模型,维护最大连续区间长度,其中区间长度就是对应的房间数目,并且对应区间中最左边的断点就是answer,同时因为需要求出连续区间的最大长度,因此每次PushUp时都将左右区间合并,lsum维护左区间的最大长度,rsum维护右区间的最大长度,sum维护区间1…N中的最大连续区间长度,cover标志对应区间是否为空(没有住客)

 

具体实现过程:

BuildTree:建立一颗线段树,其中lsum,rsum,sum初始化为对应区间的长度

Query   :询问是否有长度为a的连续区间,如果有,返回对应区间的最左边的断点

UpData  :更新线段树的信息

PushUp  :将左右子区间合并

PushDown :标志向下传,延迟标志,简单来说就是先标志,然后等到下次询问或者更新时再去更新线段树

 

代码:

  1 #include <stdio.h>

  2 

  3 #define lson l, m, rt<<1

  4 #define rson m+1, r, rt<<1|1

  5 

  6 const int maxn = 50000;

  7 

  8 int n, mNum, op, a, b;

  9 int sum[maxn*3], lsum[maxn*3], rsum[maxn*3], cover[maxn*3];

 10 

 11 void BuildTree(int l, int r, int rt)

 12 {

 13     cover[rt] = -1;

 14     lsum[rt] = rsum[rt] = sum[rt] = r-l+1;

 15     if (l == r)

 16         return ;

 17     

 18     int m = (l+r)>>1;

 19     BuildTree(lson);

 20     BuildTree(rson);

 21 }/* BuildTree */

 22 

 23 void PushDown(int rt, int k)

 24 {

 25     if (cover[rt] != -1)

 26     {   /* Lazy Tag */

 27         cover[rt<<1] = cover[rt<<1|1] = cover[rt];

 28         lsum[rt<<1] = rsum[rt<<1] = sum[rt<<1] = cover[rt] ? 0:(k-(k>>1)); 

 29         lsum[rt<<1|1] = rsum[rt<<1|1] = sum[rt<<1|1] = cover[rt] ? 0:(k>>1);

 30         cover[rt] = -1;

 31     }

 32 }/* PushDown */

 33 

 34 int query(int w, int l, int r, int rt)

 35 {

 36     if (l == r)

 37         return 1;

 38     

 39     PushDown(rt, r-l+1);    /* Push Down */

 40     

 41     int m = (l+r)>>1;

 42     if (sum[rt<<1] >= w)    /* 左连续区间长度 */ 

 43         return query(w, lson);

 44     else if (rsum[rt<<1]+lsum[rt<<1|1] >= w) /* 左区间后半部分与右区间左半部分长度 */ 

 45         return m-rsum[rt<<1]+1;

 46     else                    /* 右连续区间长度 */ 

 47         return query(w, rson);

 48 }/* query */

 49 

 50 int Max(int x, int y)

 51 {

 52     return (x>y ? x:y);

 53 }/* Max */

 54 

 55 void PushUp(int rt, int k)

 56 {

 57     lsum[rt] = lsum[rt<<1];   /* 左区间的左半部分 */ 

 58     rsum[rt] = rsum[rt<<1|1]; /* 右区间的右半部分 */ 

 59     

 60     if (lsum[rt] == k-(k>>1))

 61         lsum[rt] += lsum[rt<<1|1];

 62     if (rsum[rt] == k>>1)

 63         rsum[rt] += rsum[rt<<1];

 64     

 65     sum[rt] = Max(rsum[rt<<1]+lsum[rt<<1|1], Max(sum[rt<<1], sum[rt<<1|1]));

 66 }/* PushUp */

 67 

 68 void UpData(int L, int R, int c, int l, int r, int rt)

 69 {

 70     if (L<=l && r<=R)

 71     {

 72         lsum[rt] = rsum[rt] = sum[rt] = c ? 0 : r-l+1;

 73         cover[rt] = c;

 74         

 75         return ;

 76     }/* End of If */

 77     

 78     PushDown(rt, r-l+1);    /* Push Down */

 79     

 80     int m = (l+r)>>1;

 81     if (L <= m)

 82         UpData(L, R, c, lson);

 83     if (R > m)

 84         UpData(L, R, c, rson);

 85     

 86     PushUp(rt, r-l+1);      /* Push Up */

 87 }/* Updata */

 88 

 89 int main()

 90 {

 91     scanf("%d %d", &n, &mNum);

 92     

 93     BuildTree(1, n, 1); /* BuildTree */ 

 94     for (int i=1; i<=mNum; ++i)

 95     {

 96         scanf("%d", &op);

 97         if (op == 1)

 98         {   // Request

 99             scanf("%d", &a);

100             if (sum[1] < a)

101                 printf("0\n");  /* No result */

102             else

103             {

104                 int pos = query(a, 1, n, 1);

105                 printf("%d\n", pos);

106                 UpData(pos, pos+a-1, 1, 1, n, 1);   /* UpData the interval */

107             }

108         }/* End of If */

109         else

110         {

111             scanf("%d %d", &a, &b);

112             UpData(a, a+b-1, 0, 1, n, 1);   /* UpData the interval */

113         }

114     }/* End of For */

115     

116     return 0;

117 }

 

你可能感兴趣的:(poj)