【[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\n",now);
            if(now) change(now,now+x-1,0,1);
        }
        if(p==2) y=read(),change(x,x+y-1,1,1);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/asuldb/p/10207844.html
今日推荐