当前位置 博文首页 > 文章内容

    USACO Hotel

    作者: 栏目:未分类 时间:2020-09-21 10:00:21

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    USACO Hotel

    洛谷传送门

    JDOJ传送门

    Description

    The cows are journeying north to Thunder Bay in Canada to gain
    cultural enrichment and enjoy a vacation on the sunny shores of
    Lake Superior. Bessie, ever the competent travel agent, has named
    the Bullmoose Hotel on famed Cumberland Street as their vacation
    residence. This immense hotel has N (1 <= N <= 50,000) rooms all
    located on the same side of an extremely long hallway (all the
    better to see the lake, of course).

    The cows and other visitors arrive in groups of size D_i (1 <= D_i
    <= N) and approach the front desk to check in. Each group i requests
    a set of D_i contiguous rooms from Canmuu, the moose staffing the
    counter. He assigns them some set of consecutive room numbers
    r..r+D_i-1 if they are available or, if no contiguous set of rooms
    is available, politely suggests alternate lodging. Canmuu always
    chooses the value of r to be the smallest possible.

    Visitors also depart the hotel from groups of contiguous rooms.
    Checkout i has the parameters X_i and D_i which specify the vacating
    of rooms X_i..X_i+D_i-1 (1 <= X_i <= N-D_i+1). Some (or all) of
    those rooms might be empty before the checkout.

    Your job is to assist Canmuu by processing M (1 <= M < 50,000)
    checkin/checkout requests. The hotel is initially unoccupied.

    Input

    * Line 1: Two space-separated integers: N and M

    * Lines 2..M+1: Line i+1 contains request expressed as one of two
    possible formats: (a) Two space separated integers
    representing a check-in request: 1 and D_i (b) Three
    space-separated integers representing a check-out: 2, X_i, and
    D_i

    Output

    * Lines 1.....: For each check-in request, output a single line with a
    single integer r, the first room in the contiguous sequence of
    rooms to be occupied. If the request cannot be satisfied,
    output 0.

    Sample Input

    10 6 1 3 1 3 1 3 1 3 2 5 5 1 6

    Sample Output

    1 4 7 0 5


    最优解声明:

    emm...换个了号刷题(冲其他人借的号,并非新号),刷了双份最优解,懂得自然懂(狗头保命

    题解:

    这道题和小白逛公园有一点神似。

    蒟蒻在这里瞎xx总结一下:类似这种区间最优化问题,都可以往这边想一想:既然线段树只维护一个信息没有办法转移,就多维护几个信息。类似这种“区间连续最优化”的问题,就尝试着维护\(lmax[]/rmax[]\)数组,然后进行线段树上的维护和转移。(肤浅之见,欢迎指正)

    这样想的话,这道题的状态就比较好想了:令\(tree[]\)表示区间最长连续空房多长,\(lmax[]/rmax[]\)分别表示从左/从右开始的最长连续空房多长,\(len[]\)表示区间总长。

    转移也和小白逛公园相似。需要注意的是,小白逛公园因为不需要维护“连续为空”,而只需要维护“最大子段和”,所以无脑max就可以。但是这道题需要加一个判断。如\(pushup()\)函数所示,应该很容易看懂。

    最后分享蒟蒻在lazy标记上犯下的一个错误:这道题的lazy标记有两种。一种是开房,一种是退房。这都比较好维护。但是需要注意的是,这道题不能无脑下传lazy标记,也就是需要判断lazy标记是否为0,是0的话就不能下传。原理很简单,如果下传0的话,可能会导致已经有lazy标记的节点的lazy标记被清空。如果是普通线段树,单纯维护和的话,就可以无脑下传,因为lazy+0对其毫无影响。

    数据结构的题细节很多,还要多多注意。

    附AC代码:

    #include<cstdio>
    #include<algorithm>
    #define lson pos<<1
    #define rson pos<<1|1
    using namespace std;
    const int maxn=5*1e4+10;
    int n,m;
    int tree[maxn<<2],lmax[maxn<<2],rmax[maxn<<2],len[maxn<<2],lazy[maxn<<2];
    void pushup(int pos)
    {
        len[pos]=len[lson]+len[rson];
        if(lmax[lson]==len[lson])
            lmax[pos]=len[lson]+lmax[rson];
        else
            lmax[pos]=lmax[lson];
        if(rmax[rson]==len[rson])
            rmax[pos]=len[rson]+rmax[lson];
        else
            rmax[pos]=rmax[rson];
        tree[pos]=max(max(tree[lson],tree[rson]),lmax[rson]+rmax[lson]);
    }
    void build(int pos,int l,int r)
    {
        int mid=(l+r)>>1;
        if(l==r)
        {
            tree[pos]=lmax[pos]=rmax[pos]=len[pos]=1;
            return;
        }
        build(lson,l,mid);
        build(rson,mid+1,r);
        pushup(pos);
    }
    void mark(int pos,int l,int r,int k)
    {
        lazy[pos]=k;
        if(k==1)//住人
            tree[pos]=lmax[pos]=rmax[pos]=0;
        if(k==2)//退房
            tree[pos]=lmax[pos]=rmax[pos]=len[pos];
    }
    void pushdown(int pos,int l,int r)
    {
        if(!lazy[pos])
            return;
        int mid=(l+r)>>1;
        mark(lson,l,mid,lazy[pos]);
        mark(rson,mid+1,r,lazy[pos]);
        lazy[pos]=0;
    }
    void update(int pos,int l,int r,int x,int y,int k)
    {
        int mid=(l+r)>>1;
        if(x<=l && r<=y)
        {
            mark(pos,l,r,k);
            return;
        }
        pushdown(pos,l,r);
        if(x<=mid)
            update(lson,l,mid,x,y,k);
        if(y>mid)
            update(rson,mid+1,r,x,y,k);
        pushup(pos);
    }
    int query(int pos,int l,int r,int x)
    {
        int mid=(l+r)>>1;
        if(l==r)
            return l;
        pushdown(pos,l,r);
        if(tree[lson]>=x)
            return query(lson,l,mid,x);
        if(lmax[rson]+rmax[lson]>=x)
            return mid-rmax[lson]+1;
        return query(rson,mid+1,r,x);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        build(1,1,n);
        while(m--)
        {
            int opt,x,y;
            scanf("%d",&opt);
            if(opt==1)
            {
                scanf("%d",&x);
                if(tree[1]>=x)
                {
                    int ans=query(1,1,n,x);
                    printf("%d\n",ans);
                    update(1,1,n,ans,ans+x-1,1);//1为住人
                }
                else
                    puts("0");
            }
            else
            {
                scanf("%d%d",&x,&y);
                update(1,1,n,x,x+y-1,2);//2为退房
            }
        }
        return 0;
    }