[POJ3667]Hotel

Posted 小飞淙的云端

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[POJ3667]Hotel相关的知识,希望对你有一定的参考价值。

题目描述 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 Di (1 ≤ Di ≤ N) and approach the front desk to check in. Each group i requests a set of Di contiguous rooms from Canmuu, the moose staffing the counter. He assigns them some set of consecutive room numbers r..r+Di-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 Xi and Di which specify the vacating of rooms Xi ..Xi +Di-1 (1 ≤ Xi ≤ N-Di+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 Description

* 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(b) Three space-separated integers representing a check-out: 2, Xi, and Di

输出描述 Output Description
  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
数据范围及提示 Data Size & Hint
 

英文不是一般的差!!!看不懂的话,翻译一下题面:

输入n,m;  n代表1-n的区间,m代表有m个操作。对于每个操作如果先输入1,则输入w,找到区间最左边未被占用的连续长度为w的区间,返回左端点,并把这段区间标记为已被占用。如果整个区间没有找到符合条件的区间。则返回0。如果输入为2,则将这段区间标记为未被占用。

这下看的就爽多了。

首先这是一道数据结构题。然后我们继续看,发现这和动态求最大连续和不相类似,于是我们就套路一波:

mlen[o]区间最大连续和,ml[o]最大前缀和 mr[o]最长后缀和

然后我们来看操作1,由于要求是尽量往左找,(mlen[lo]>=len)所以在query的时候要尽量往左找,左边不行就看中间一段,即mr[lo]+ml[ro]>=len的情况,最后只能到右边去找了。找到答案之后需要区间修改一下那段数的值。操作2就很简单了,直接区间修改成0.

PS:这道题省选集训的时候老师提问过,虽然当时我这题A了,但是我并没有想好该怎么讲,然而比较悲惨的是老师直接叫我了,然后我一阵瞎讲弄得无比尴尬。。、

技术分享
#include<iostream> 
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef long long LL;
#define mem(a,b) memset(a,b,szieof(a))
typedef pair<int,int> PII;
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c==-)f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-0;c=getchar();}
    return x*f;
}
const int maxn=50010;
int n,m,tp,d,x,mlen[4*maxn],ml[4*maxn],mr[4*maxn],tag[4*maxn],ans;
void pushup(int l,int r,int o)
{
    int mid=(l+r)>>1,lo=o<<1,ro=lo|1;
    mlen[o]=max(max(mlen[lo],mlen[ro]),mr[lo]+ml[ro]);
    mr[o]=mr[ro];ml[o]=ml[lo];
    if(mlen[ro]==r-mid)mr[o]=r-mid+mr[lo];
    if(mlen[lo]==mid-l+1)ml[o]=mid-l+1+ml[ro];
} 
void pushdown(int l,int r,int o)
{
    int mid=(l+r)>>1,lo=o<<1,ro=lo|1;
    if(tag[o]==-1)return;
    tag[lo]=tag[ro]=tag[o];
    if(tag[o])mlen[lo]=ml[lo]=mr[lo]=mlen[ro]=ml[ro]=mr[ro]=0;
    else 
    {
        mlen[lo]=ml[lo]=mr[lo]=mid-l+1;
        mlen[ro]=ml[ro]=mr[ro]=r-mid;
    }
    tag[o]=-1;
}
void build(int l,int r,int o)
{
    mlen[o]=ml[o]=mr[o]=r-l+1;
    if(l==r)return;
    int mid=(l+r)>>1,lo=o<<1,ro=lo|1;
    build(l,mid,lo);build(mid+1,r,ro);
}
void update(int l,int r,int o,int L,int R,int change)
{
    if(l==L && r==R)
    {
        tag[o]=change;
        if(change)mlen[o]=ml[o]=mr[o]=0;
        else mlen[o]=ml[o]=mr[o]=r-l+1;
        return;
    }
    pushdown(l,r,o);
    int mid=(l+r)>>1,lo=o<<1,ro=lo|1;
    if(R<=mid)update(l,mid,lo,L,R,change);
    else if(L>mid)update(mid+1,r,ro,L,R,change);
    else
    {
        update(l,mid,lo,L,mid,change);
        update(mid+1,r,ro,mid+1,R,change);
    }
    pushup(l,r,o);
}
int query(int l,int r,int o,int len)
{
    if(l==r)return l;
    int mid=(l+r)>>1,lo=o<<1,ro=lo|1;
    pushdown(l,r,o);
    if(mlen[lo]>=len)return query(l,mid,lo,len);
    else if(mr[lo]+ml[ro]>=len)return mid-mr[lo]+1;
    return query(mid+1,r,ro,len);
} 
int main()
{
    n=read();m=read();
    build(1,n,1);
    while(m--)
    {
        tp=read();
        if(tp==1)
        {
            d=read();
            if(mlen[1]<d)
            {
                printf("0\n");
                continue;
            }
            ans=query(1,n,1,d);
            printf("%d\n",ans);
            update(1,n,1,ans,d+ans-1,1);
        }
        else
        {
            x=read();d=read();
            update(1,n,1,x,x+d-1,0);
        }
    }
    return 0;
}
View Code

 


以上是关于[POJ3667]Hotel的主要内容,如果未能解决你的问题,请参考以下文章

线段树区间合并POJ3667-Hotel

POJ 3667 Hotel

POJ 3667 Hotel

poj 3667 Hotel - 线段树

[POJ3667]Hotel

Hotel poj 3667