• 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;
    }
  • 相关阅读:
    c++获取线程id
    一个基于c++的log库
    防止socket程序重启等待2MSL时间
    c++头文件循环引用
    Myeclipse 8.5 优化设置
    来道题 求解释
    MyEclipse常用设置笔记
    Ubuntu 学习笔记
    Linux 下常用命令
    Oracle 学习笔记 常用查询命令篇
  • 原文地址:https://www.cnblogs.com/woaiyy/p/2548742.html
Copyright © 2020-2023  润新知