zoukankan      html  css  js  c++  java
  • 【[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;
    }
    
    
    
  • 相关阅读:
    memcache安装 基于Red Hat 7.4
    LNMP源码编译
    LAMP源码编译
    Red Hat 7.4 安装laravel框架 基于xampp集成环境
    PHP 扩展开发检测清单(扩展开发必读)
    20 个 Laravel Eloquent 必备的实用技巧
    [项目推荐] Corcel 让你在 WordPress 中使用 Laravel
    Tumblr:我们是如何从 PHP 5 升级到 PHP 7 的
    PHP / Laravel 月刊 #23
    十个你需要在 PHP 7 中避免的坑
  • 原文地址:https://www.cnblogs.com/asuldb/p/10207844.html
Copyright © 2011-2022 走看看