• USACO Hotel


    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
    ",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;
    }
    
  • 相关阅读:
    利用cookie实现iframe刷新时停留在当前页面
    css定位学习经验记录
    用div加css做表格去掉外围边框
    利用css中的background-position定位图片
    css3实现圆形逐渐减少动画
    The Best Path
    3998
    YAPTCHA(hdu2973)
    1556 计算
    1808: 地铁
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13703908.html
Copyright © 2020-2023  润新知