POJ 3667 Hotel(线段树)

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

题意:旅馆的N 个房间初始时全为空。现在有M个操作,分为两种:

(1)1 X,要求得到连续的X个房间,输出X个连续房间的最小编号;如果有多个X的连续房间,输出编号最小的一个;不存在输出0;

(2)2 X Y,将X开始的连续Y个房间退掉。

思路:经典的线段树题目。。。

每个节点保存max,Lmax,Rmax三个值,分别是本区间内最长的连续可用房间数,从左侧开始最长的连续可用房间数,有右侧开始最长的连续可用房间数。这样,对于询问,首先判断区间的max值是否满足,不满足可直接返回0;否则判断Lmax是否满足,满足则返回本区间的L值即可;否则判断左孩子的max值,若满足递归到左孩子;否则,判断左孩子的Rmax加上右孩子的Lmax值是否满足,是则返回左孩子Rmax段的左侧;否则递归到右孩子。对于更新,则在左右孩子返回后修改本区间的max、Lmax和Rmax值。



 

 struct node

 {

     int L,R,len,mid;

     int max,Lmax,Rmax;

 };

 

 

 const int MAX=50005;

 node a[MAX<<2];

 int n,m;

 

 

 void build(int t,int L,int R)

 {

     a[t].L=L;

     a[t].R=R;

     a[t].mid=(L+R)>>1;

     a[t].len=R-L+1;

     a[t].Lmax=a[t].Rmax=a[t].max=R-L+1;

     if(L==R) return;

     build(t*2,L,a[t].mid);

     build(t*2+1,a[t].mid+1,R);

 }

 

 int query(int t,int x)

 {

     if(a[t].max<x) return 0;

     if(a[t].Lmax>=x) return a[t].L;

     if(a[t*2].max>=x) return query(t*2,x);

     if(a[t*2].Rmax+a[t*2+1].Lmax>=x) return a[t*2].R-a[t*2].Rmax+1;

     return query(t*2+1,x);

 }

 

 void update(int t,int L,int R,int st)

 {

     if(L==a[t].L&&R==a[t].R)

     {

         a[t].max=a[t].Lmax=a[t].Rmax=st*a[t].len;

         return;

     }

     if(a[t].max==a[t].len||a[t].max==0)

     {

         a[t*2].max=a[t*2].Lmax=a[t*2].Rmax=a[t*2].len*(a[t].max!=0);

         a[t*2+1].max=a[t*2+1].Lmax=a[t*2+1].Rmax=a[t*2+1].len*(a[t].max!=0);

     }

     if(R<=a[t].mid) update(t*2,L,R,st);

     else if(L>a[t].mid) update(t*2+1,L,R,st);

     else

     {

         update(t*2,L,a[t].mid,st);

         update(t*2+1,a[t].mid+1,R,st);

     }

 

     a[t].Lmax=a[t*2].Lmax;

     if(a[t].Lmax==a[t*2].len) a[t].Lmax+=a[t*2+1].Lmax;

     a[t].Rmax=a[t*2+1].Rmax;

     if(a[t].Rmax==a[t*2+1].len) a[t].Rmax+=a[t*2].Rmax;

     a[t].max=max(a[t*2].max,a[t*2+1].max);

     a[t].max=max(a[t].max,a[t*2].Rmax+a[t*2+1].Lmax);

 }

 

 int main()

 {

     scanf("%d%d",&n,&m);

     build(1,1,n);

     int cmd,x,y,t;

     while(m--)

     {

         scanf("%d",&cmd);

         if(cmd==1)

         {

             scanf("%d",&x);

             y=query(1,x);

             printf("%d\n",y);

             if(y) update(1,y,y+x-1,0);

         }

         else

         {

             scanf("%d%d",&x,&y);

             update(1,x,x+y-1,1);

         }

     }

     return 0;

 }

  

你可能感兴趣的:(poj)