• [P2894][USACO08FEB] 酒店Hotel (线段树+懒标记下传)


    题意:有 n个房间,题目给出两个操作,若 op==1,就输出最靠左的连续空房数量为 x的房间序列的最左边的序号,然后将这些房间改为入住;若 op==2,就将从 x~y的的序列全部改为空房;

    解法:线段树+懒标记下传;

    1.线段树;题目让在一个很长的序列操作很多次,暴力显然过不了,要用线段树优化;

    2.懒标记下传;这是本题的精髓。   此题要维护的不是序列上的数值总和,而是该序列的最长连续空房的长度 sum,从该节点从左向右数最长的连续空房长度 lm,以及从该节点从右向左数最长的连续空房长度 rm;同时还要注意在合并区间时的操作;( tag==1表示要将序列变为空房; tag==2表示要将序列变为有房)

    附上代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define mid ((l+r)>>1)
    #define ls (o*2)
    #define rs (o*2+1)
    using namespace std;
    const int N = 5e4+10;
    
    inline int read(){
        int ref=0,x=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')x=-1;ch=getchar();}
        while(isdigit(ch)){ref=ref*10+ch-'0';ch=getchar();}
        return ref*x;
    }
    
    int n,m;
    struct tree{
        int sum,lm,rm,len;
    }a[N<<4];
    int tag[N<<4];
    
    void pushup(int o){
        a[o].lm=(a[ls].lm==a[ls].len)?a[ls].len+a[rs].lm:a[ls].lm;
        a[o].rm=(a[rs].rm==a[rs].len)?a[rs].len+a[ls].rm:a[rs].rm;
        a[o].sum=max(max(a[ls].sum,a[rs].sum),a[ls].rm+a[rs].lm);    
    }
    
    void pushdown(int o){
        if(!tag[o]) return ;
        tag[ls]=tag[rs]=tag[o];
        a[ls].sum=a[ls].lm=a[ls].rm=(tag[o]==1)?a[ls].len:0;
        a[rs].sum=a[rs].lm=a[rs].rm=(tag[o]==1)?a[rs].len:0;
        tag[o]=0;
    }
    
    void build(int o,int l,int r){
        a[o].len=a[o].lm=a[o].rm=a[o].sum=r-l+1;
        if(l==r) return ;
        build(ls,l,mid);
        build(rs,mid+1,r);
    }
    
    void updata(int o,int l,int r,int x,int y,int lz){
        if(x<=l&&y>=r){
            a[o].sum=a[o].lm=a[o].rm=(lz==1)?a[o].len:0;
            tag[o]=lz;
            return ;
        }
        pushdown(o);
        if(x<=mid) updata(ls,l,mid,x,y,lz);
        if(y>mid) updata(rs,mid+1,r,x,y,lz);
        pushup(o);
    }
    
    int query(int o,int l,int r,int lenth){
        pushdown(o);
        if(l==r) return l;
        if(a[ls].sum>=lenth) return query(ls,l,mid,lenth);
        if(a[ls].rm+a[rs].lm>=lenth) return mid-a[ls].rm+1;
        else return query(rs,mid+1,r,lenth);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        build(1,1,n);
        for(int i=1;i<=m;i++){
            int x,y,op;
            op=read();
            if(op==1){
                x=read();
                if(a[1].sum>=x){
                    int ans=query(1,1,n,x);
                    printf("%d
    ",ans);
                    updata(1,1,n,ans,ans+x-1,2);
                }
                else printf("0
    ");
            }
            else {
                x=read(),y=read();
                updata(1,1,n,x,x+y-1,1);
            }
        }
        return 0;
    }
  • 相关阅读:
    例2-3
    例2-2
    例2-1
    p14
    第一次作业
    例1-1
    第二次作业(2)
    第二次作业
    第三章3-3
    第三章3-2
  • 原文地址:https://www.cnblogs.com/nnezgy/p/11396850.html
Copyright © 2020-2023  润新知