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

题目链接:http://poj.org/problem?id=3667

最初给你n间空房,m个操作:

  操作1 a 表示检查是否有连续的a间空房,输出最左边的空房编号,并入住a间房间。

  操作2 a b 表示将编号为a之后的b间房间清空。

典型的区间合并问题,这位大牛讲的更清楚:http://www.cnblogs.com/yewei/archive/2012/05/05/2484471.html

代码如下:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 using namespace std;
  5 const int MAXN = 5e4 + 5;
  6 //sum表示这个区间的最大数,lsum表示从这个区间最左边开始连续的最大数,rsum与lsum方向相反
  7 struct data {
  8     int l , r , lsum , rsum , sum , cover;
  9 }T[MAXN << 2];
 10 
 11 void build(int p , int l , int r) {
 12     int mid = (l + r) >> 1;
 13     T[p].lsum = T[p].rsum = T[p].sum = r - l + 1;
 14     T[p].cover = -1;
 15     T[p].l = l , T[p].r = r;
 16     if(l == r)
 17         return ;
 18     build(p << 1 , l , mid);
 19     build((p << 1)|1 , mid + 1 , r);
 20 }
 21 
 22 void Pushdown(int p) {
 23     if(T[p].cover != -1) {
 24         int ls = p << 1 , rs = (p << 1)|1;
 25         T[ls].cover = T[rs].cover = T[p].cover;
 26         T[ls].lsum = T[ls].rsum = T[ls].sum = T[p].cover ? 0 : T[ls].r - T[ls].l + 1;
 27         T[rs].lsum = T[rs].rsum = T[rs].sum = T[p].cover ? 0 : T[rs].r - T[rs].l + 1;
 28         T[p].cover = -1;
 29     }
 30 }
 31 
 32 void Pushup(int p) {
 33     T[p].lsum = T[p << 1].lsum;
 34     T[p].rsum = T[(p << 1)|1].rsum;
 35     if(T[p].lsum == T[p << 1].r - T[p << 1].l + 1)
 36         T[p].lsum += T[(p << 1)|1].lsum;
 37     if(T[p].rsum == T[(p << 1)|1].r - T[(p << 1)|1].l + 1)
 38         T[p].rsum += T[p << 1].rsum;
 39     int temp = max(T[(p << 1)|1].sum , T[p << 1].rsum + T[(p << 1)|1].lsum);
 40     T[p].sum = max(T[p << 1].sum , temp);
 41 }
 42 
 43 int query(int p , int len) {
 44     int mid = (T[p].l + T[p].r) >> 1;
 45     if(T[p].l == T[p].r) {
 46         return T[p].l;
 47     }
 48     Pushdown(p);
 49     if(T[p << 1].sum >= len) { //左孩子区间的最大数,优先选左孩子
 50         return query(p << 1 , len);
 51     }
 52     else if(T[p << 1].rsum + T[(p << 1)|1].lsum >= len) { //其次要是左孩子的rsum和右孩子的lsum 加起来大于len
 53         return mid - T[p << 1].rsum + 1;
 54     }
 55     else {
 56         return query((p << 1)|1 , len); //最后就是右孩子
 57     }
 58 }
 59 
 60 void updata(int p , int l , int r , int flag) {
 61     int mid = (T[p].l + T[p].r) >> 1;
 62     if(T[p].l == l && T[p].r == r) {
 63         T[p].sum = T[p].lsum = T[p].rsum = flag ? 0 : r - l + 1;
 64         T[p].cover = flag;
 65         return ;
 66     }
 67     Pushdown(p);
 68     if(r <= mid) {
 69         updata(p << 1 , l , r , flag);
 70     }
 71     else if(l > mid) {
 72         updata((p << 1)|1 , l , r , flag);
 73     }
 74     else {
 75         updata(p << 1 , l , mid , flag);
 76         updata((p << 1)|1 , mid + 1 , r , flag);
 77     }
 78     Pushup(p);
 79 }
 80 
 81 int main()
 82 {
 83     int n , m , choose , u , v;
 84     while(~scanf("%d %d" , &n , &m)) {
 85         build(1 , 1 , n);
 86         while(m--) {
 87             scanf("%d" , &choose);
 88             if(choose == 1) {
 89                 scanf("%d" , &u);
 90                 if(T[1].sum < u)
 91                     printf("0\n");
 92                 else {
 93                     int pos = query(1 , u);
 94                     printf("%d\n" , pos);
 95                     updata(1 , pos , pos + u - 1 , 1);
 96                 }
 97             }
 98             else {
 99                 scanf("%d %d" , &u , &v);
100                 updata(1 , u , min(u + v - 1 , n) , 0);
101             }
102         }
103     }
104     return 0;
105 }

 

posted @ 2016-05-26 22:31  Recoder  阅读(139)  评论(0编辑  收藏  举报