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;
}
原文地址:https://www.cnblogs.com/woaiyy/p/2548742.html