• 【[USACO08FEB]酒店Hotel】


    比较基础的线段树了

    我们要维护最大连续子串,这个可以说是一个比较套路的操作了

    我们在[SHOI2009]会场预约这道题中已经比较深刻的认识到了这个套路了

    对于这道题,我们显然要知道一个区间内最大的全为1(我的代码里用1表示空房)子串长度是多少,那怎么办呢

    我们多开几个数组

    (d[i])表示(i)这个区间内最大的全为1子串长度

    (rc[i])表示(i)这个区间内从左端开始的最大全为1子串长度

    (lc[i])表示(i)这个区间内从右端开始的最大全为1子串长度

    于是我们做pushup操作的时候要注意一点,就是某个区间的左端已经全是1,那么(lc[i])要等于左区间长度加上右区间左端的最大全为1子串长度,当然右区间全是1也同理

    所以我们这道题就比较好做了

    查询的时候自然是先查左区间,如果左区间没有答案,那么我们就再找左右区间中间的部分,即(rc[i<<1]+lc[i<<1|1]),如果这个长度大于等于我们要找的长度,我们就可以直接返回了,否则我们再去找右区间

    于是就是代码了

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define maxn 50001
    using namespace std;
    int l[maxn<<2],r[maxn<<2],tag[maxn<<2],rc[maxn<<2],lc[maxn<<2],d[maxn<<2];
    int n,m;
    inline int read()
    {
        char c=getchar();
        int x=0;
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9')
          x=(x<<3)+(x<<1)+c-48,c=getchar();
        return x;
    }
    inline void pushup(int i)
    {
        if(d[i<<1]==r[i<<1]-l[i<<1]+1) lc[i]=lc[i<<1]+lc[i<<1|1];
        else lc[i]=lc[i<<1];
        //这里if的条件最开始写成了d[i<<1]==lc[i<<1],wa了好久,以后看这道题想想为什么
        if(d[i<<1|1]==r[i<<1|1]-l[i<<1|1]+1) rc[i]=rc[i<<1|1]+rc[i<<1];
        else rc[i]=rc[i<<1|1];
        d[i]=max(d[i<<1],max(d[i<<1|1],rc[i<<1]+lc[i<<1|1]));
    }
    inline void pushdown(int i)
    {
        if(tag[i]==-1) return;
        tag[i<<1]=tag[i];
        tag[i<<1|1]=tag[i];
        lc[i<<1]=rc[i<<1]=d[i<<1]=(r[i<<1]-l[i<<1]+1)*tag[i];
        lc[i<<1|1]=rc[i<<1|1]=d[i<<1|1]=(r[i<<1|1]-l[i<<1|1]+1)*tag[i];
        tag[i]=-1;
    }
    void build(int x,int y,int i)
    {
        l[i]=x;
        r[i]=y;
        tag[i]=-1;
        if(x==y)
        {
            rc[i]=lc[i]=d[i]=1;
            return;
        }
        int mid=x+y>>1;
        build(x,mid,i<<1);
        build(mid+1,y,i<<1|1);
        pushup(i);
    }
    void change(int x,int y,int v,int i)
    {
        if(x<=l[i]&&y>=r[i])
        {
            d[i]=lc[i]=rc[i]=(r[i]-l[i]+1)*v;
            tag[i]=v;
            return;
        }
        pushdown(i);
        int mid=l[i]+r[i]>>1;
        if(y<=mid) change(x,y,v,i<<1);
        else if(x>mid) change(x,y,v,i<<1|1);
        else change(x,y,v,i<<1|1),change(x,y,v,i<<1);
        pushup(i);
    }
    int query(int now,int i)
    {
        pushdown(i);
        int mid=l[i]+r[i]>>1;
        if(l[i]==r[i]) return l[i];
        if(d[i<<1]>=now) return query(now,i<<1);
        if(rc[i<<1]&&rc[i<<1]+lc[i<<1|1]>=now) return (mid-rc[i<<1]+1);
        if(d[i<<1|1]>=now) return query(now,i<<1|1);
    }
    //int ask(int p,int ll,int rr,int length)
    //{
    //    pushdown(p);
    //    if(ll==rr)return ll;
    //    int mid=(ll+rr)>>1;
    //    if(d[p<<1]>=length)return ask(p<<1,ll,mid,length);
    //    if(rc[p<<1]+lc[p<<1|1]>=length) return mid-rc[p<<1]+1;
    //    else return ask(p<<1|1,mid+1,rr,length);
    //    return 0;
    //}
    int main()
    {
        n=read();
        m=read();
        build(1,n,1);
        int p,x,y;
        while(m--)
        {
            p=read();
            x=read();
            if(p==1)
            {
                int now;
                if(d[1]>=x) now=query(x,1);
                else now=0;
                printf("%d
    ",now);
                if(now) change(now,now+x-1,0,1);
            }
            if(p==2) y=read(),change(x,x+y-1,1,1);
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    莫队总结
    三、模型层(二)
    二、模型层(一)
    五、web杂项
    一. Django入门
    二、js
    一、html和css
    二十一、正则表达式
    END:小练习、涨知识
    二十、协程
  • 原文地址:https://www.cnblogs.com/asuldb/p/10207844.html
Copyright © 2020-2023  润新知