NYOJ250 ROOM ASSIGNATION || POJ3667 Hotel

  1 /*

  2   Name: 

  3   Copyright: 

  4   Author: 

  5   Date: 28/04/13 21:55

  6   Description: 

  7         刚开始做这道题的时候,第一感觉用线段树应该很容易实现,结果发现我没做过此类的线段树题目

  8         然后上网看了别人的代码,才了有点思路,现总结如下:

  9         这道题题意就是旅馆订房问题,由于牵扯到某一段区间的查找与运算,所以选择了线段树求解,

 10         用free表示此段区间房间是否可用,lmax代表这段区间从左边起最长空闲房间数,rmax表示这段区间

 11         从右边起最长空闲房间数,tmax表示整个区间上的最长连续空闲房间数,查找连续空房间数时,过程如下:

 12             1、如果1~n区间的tmax值都比待查长度len小,就无解,否则有解执行2 

 13             2、假如区间lmax是否大于等于len,直接返回l ,否则执行3 

 14             3、对于每一个区间,如果它的左儿子的tmax值大于等于len,到左儿子里去找。否则执行4 

 15             4、如果左儿子的rmax加上有儿子的lmax大于等于len,直接返回左儿子的右端点减去左儿子的rmax值。

 16             5、否则到右儿子里去找。

 17             PS:对于上述过程,如果满足前面的条件,则不再考虑后面的情况。

 18          更新的时候既进行下压操作,在对某段区间进行处理后(清空房间或占用房间)后,进行更新父节点,

 19          细节看注释!! 

 20 */

 21 #include<iostream>

 22 #include<cstdio>

 23 const int N=50010;

 24 using namespace std;

 25 struct Node{

 26     int l,r;

 27     int free;

 28     int lmax,rmax,tmax; 

 29 }tree[3*N];

 30 int build(int l,int r,int i){

 31     tree[i].l=l;

 32     tree[i].r=r;

 33     tree[i].lmax=tree[i].rmax=tree[i].tmax=r-l+1; //初始化为区间大小 

 34     tree[i].free=0;

 35     if(l<r){

 36         int mid=(l+r)>>1;

 37         build(l,mid,i<<1);

 38         build(mid+1,r,i<<1|1);

 39     }

 40 }

 41 int query(int i,int len){

 42     if(tree[i].tmax<len) return 0;  //情况1

 43     if(tree[i].lmax>=len) return tree[i].l;  //情况2 

 44     if(tree[i<<1].tmax>=len) return query(i<<1,len); //情况3 

 45     else if(tree[i<<1].rmax+tree[i<<1|1].lmax >= len) //情况4 

 46         return tree[i<<1].r-tree[i<<1].rmax+1;

 47     else return query(i<<1|1,len); //情况5

 48 }

 49 int update(int l,int r,int i,int state){

 50     if(tree[i].l==l&&tree[i].r==r){ //找到此段区间 

 51         tree[i].free=state;

 52         if(state){ //若为1则占用房间 ,否则腾出房间 

 53             tree[i].lmax=tree[i].rmax=tree[i].tmax=0;

 54         }else{

 55             tree[i].lmax=tree[i].rmax=tree[i].tmax=tree[i].r-tree[i].l+1;

 56         }

 57     }else if(tree[i].r > tree[i].l){

 58         if(tree[i].free==1){  //树节点的相应信息向下压,即节点信息细致化 

 59             tree[i<<1].free=tree[i<<1|1].free=1;

 60             tree[i<<1].lmax=tree[i<<1].rmax=tree[i<<1].tmax=0;

 61             tree[i<<1|1].lmax=tree[i<<1|1].rmax=tree[i<<1|1].tmax=0;

 62         }

 63         if(tree[i].free==0){

 64             tree[i<<1].free=tree[i<<1|1].free=0;

 65             tree[i<<1].lmax=tree[i<<1].rmax=tree[i<<1].tmax=tree[i<<1].r-tree[i<<1].l+1;

 66             tree[i<<1|1].lmax=tree[i<<1|1].rmax=tree[i<<1|1].tmax=tree[i<<1|1].r-tree[i<<1|1].l+1;

 67         }

 68         int mid=(tree[i].r+tree[i].l)>>1;

 69         if(mid>=r) update(l,r,i<<1,state);

 70         else if(mid<l) update(l,r,i<<1|1,state);

 71         else{

 72             update(l,mid,i<<1,state);

 73             update(mid+1,r,i<<1|1,state);

 74         }

 75         tree[i].lmax=tree[i<<1].lmax;  //树节点相应信息向上推送,即更新父节点信息 

 76         tree[i].rmax=tree[i<<1|1].rmax;

 77         if(tree[i<<1].free==0) tree[i].lmax+=tree[i<<1|1].lmax;

 78         if(tree[i<<1|1].free==0) tree[i].rmax+=tree[i<<1].rmax;

 79         tree[i].tmax=max(tree[i<<1].tmax,tree[i<<1|1].tmax);  //选取左孩子tmax和右孩子tmax及左右之间结合的最大值 

 80         tree[i].tmax=max(tree[i].tmax,tree[i<<1].rmax+tree[i<<1|1].lmax);

 81         if(tree[i<<1].free==tree[i<<1|1].free)  //更新父节点的使用情况 

 82             tree[i].free=tree[i<<1].free;

 83         else tree[i].free=-1;

 84     }

 85 }

 86 int main()

 87 {

 88     int N,M,s,num,start,flag;

 89     while(~scanf("%d%d",&N,&M)){

 90         build(1,N,1);

 91         while(M--){

 92             scanf("%d",&flag);

 93             if(flag==1){

 94                 scanf("%d",&s);

 95                 start=query(1,s); //start为0说明未找到符合房间 

 96                 printf("%d\n",start);

 97                 if(start) update(start,start+s-1,1,1);  //假如 start不为零,那么就需要占用 

 98             }else{

 99                 scanf("%d%d",&s,&num);

100                 update(s,s+num-1,1,0);

101             }

102         }

103     }

104     return 0;

105 }

 

你可能感兴趣的:(sign)