poj 3667 Hotel

变量,此题维持3个变量,假设区间l[l,r]这个区间需要保存这个区间的最大值,从l开始的最大值,以及以r结尾的最大值,对于COVER空闲为1,非空闲为0.

大概思路:对与1:先query操作找出能够容纳给定范围的第一个下标,然后update更新操作。

              对于2:操作直接update操作

query操作:根据大小需要的连续房间进行qury操作,当然要先进行pushdown操作,即将当前节点cover状态赋予子代, 然后如果这个需要的房间大小如果小于其左孩子的大小

                则访问孩子,另外如果是左孩子的右最大值+右孩子的左孩子最大值 大于value,很明显,就是直接左边孩子的开始处,如果都不是,则剩下的是右孩子了。。

pushdow:操作就只有一个功能判断当前节点被什么覆盖,如果COVER不为-1,则被0或者是1覆盖,然后直接将其孩子的区间就是全为覆盖值乘以其范围,如果为-1,不需要覆

                操作。

update:根据更新区间操作,如果除开pushup那一部分就是一个更新区间为1或者0的操作。

pushup:一个区间(称为S):    的左最大是看左孩子的左最大,如果左孩子的左最大等于自身的区间,则S的左最大还需要包括S右孩子的左最大,同理S区间的右最大也是如此。

           然后S区间的最大值就为左孩子的最大值,或者右孩子的最大值,或者是左孩子的右最大与右孩子的左最大之和。

#include<cstdio>

#include<cstdlib>

#include<cmath>

#include<cstring>

#define MAXN 55555

int lmax[MAXN<<2],rmax[MAXN<<2],mmax[MAXN<<2],cover[MAXN<<2];

void build(int l,int r,int id);

void update(int left,int right,int l,int r,int id,int value);

int query(int value,int l,int r,int id);

void pushdown(int id,int l,int r);

void pushup(int id,int l,int r);

int max(int a,int b);

int main()

{

     int n,m,op,value,left,right,i;

     while(scanf("%d%d",&n,&m)==2)

     {

         build(1,n,1);

         while(m--)

         {

             scanf("%d",&op);

             if(op==1)

             {

                 scanf("%d",&value);

                 if(value>mmax[1])

                     printf("0\n");

                 else

                 {

                   left=query(value,1,n,1);

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

                   update(left,left+value-1,1,n,1,0);



                 }

             }

             else

             {

                 scanf("%d%d",&left,&right);

                 update(left,left+right-1,1,n,1,1);

             }

         }





     }





}

void build(int l,int r,int id)

{

    lmax[id]=rmax[id]=mmax[id]=(r-l+1);

    cover[id]=-1;

    if(l==r)

        return;

        int mid=l+r>>1;

    build(l,mid,id<<1);

    build(mid+1,r,id<<1|1);

}

void update(int left,int right,int l,int r,int id,int value)

{

    if(left<=l&&right>=r)

    {

        cover[id]=value;

        rmax[id]=mmax[id]=lmax[id]=(r-l+1)*value;

        return ;





    }

    if(l==r)

    return ;

    int mid=l+r>>1;

    pushdown(id,l,r);

    if(left<=mid)

        update(left,right,l,mid,id<<1,value);

    if(right>mid)

        update(left,right,mid+1,r,id<<1|1,value);

    pushup(id,l,r);









}

int query(int value,int l,int r ,int id)

{

    if(l==r)

        return l;

        pushdown(id,l,r);

    int mid=l+r>>1;

    if(mmax[id<<1]>=value)

          return query(value,l,mid,id<<1);

    else if(rmax[id<<1]+lmax[id<<1|1]>=value)

        return mid-rmax[id<<1]+1;

    else return query(value,mid+1,r,id<<1|1);

    //pushup(id,l,r);

}

void pushdown(int id,int l,int r)

{

    if(cover[id]!=-1)

    {

        int mid=l+r>>1;

        cover[id<<1]=cover[id<<1|1]=cover[id];

        lmax[id<<1]=mmax[id<<1]=rmax[id<<1]=(mid-l+1)*cover[id];

        lmax[id<<1|1]=rmax[id<<1|1]=mmax[id<<1|1]=(r-mid)*cover[id];

        cover[id]=-1;

    }

}

void pushup(int id,int l,int r)

{

    int mid=r+l>>1;

   rmax[id]=rmax[id<<1|1]+((rmax[id<<1|1]==r-mid)?rmax[id<<1]:0);

   lmax[id]=lmax[id<<1]+((lmax[id<<1]==mid-l+1)?lmax[id<<1|1]:0);

   mmax[id]=max(max(mmax[id<<1],mmax[id<<1|1]),rmax[id<<1]+lmax[id<<1|1]);

}

int max(int a,int b)

{

    return a>=b?a:b;

}

你可能感兴趣的:(poj)