POJ 3667 - Hotel

原创 2016年08月29日 19:36:52

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 numbersr..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 ofr to be the smallest possible.

Visitors also depart the hotel from groups of contiguous rooms. Checkout i has the parameters Xi andDi which specify the vacating of rooms Xi ..Xi +Di-1 (1 ≤XiN-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

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


Output

* Lines 1.....: For each check-in request, output a single line with a single integerr, 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


题意:在一个旅馆里申请房间,第一行两个数字 N,M。表示有 N 个房间,M 次操作。下面有 M 行,每行两个数字,前一个数字1是申请房间,后面的数字是申请的房间数目,并且返回申请房间的第一个的房间号,申请的房间必须是连续的。如果是2,后面有两个数字,表示从 a 到 b 的房间都清空。


只要设计好线段树,sum数组表示这段中最多的连续的房间,lsum表示从左边开始连续的房间有多少个,rsum则是从右边。sym用来记录一共有多少空房间。

每次申请房间时,看从左边能否直接申请到连续的房间,再看左边的右半段和右边的左半段合起来能否满足要求,最后是右边剩下的。

#include <stdio.h>

const int maxn = 50000;
int sum[maxn*3], lsum[maxn*3], rsum[maxn*3], sym[maxn*3];

void BuildTree(int left, int right, int root);
void UpData(int L, int R, int c, int left, int right, int root);
void PushDown(int root, int k);
void PushUp(int root, int k);
int query(int w, int left, int right, int root);
int Max(int x, int y)
{
    return x>y ? x:y;
}

int main()
{
    int n, mNum, op, a, b;
    scanf("%d %d", &n, &mNum);

    BuildTree(1, n, 1);
    for (int i=1; i<=mNum; ++i)
    {
        scanf("%d", &op);
        if (op == 1)
        {
            scanf("%d", &a);
            if (sum[1] < a)
                printf("0\n");
            else
            {
                int pos = query(a, 1, n, 1);
                printf("%d\n", pos);
                UpData(pos, pos+a-1, 1, 1, n, 1);
            }
        }
        else
        {
            scanf("%d %d", &a, &b);
            UpData(a, a+b-1, 0, 1, n, 1);
        }
    }
    return 0;
}

void BuildTree(int left, int right, int root)
{
    sym[root] = -1;
    lsum[root] = rsum[root] = sum[root] = right-left+1;
    if (left == right)
        return;

    int mid = (left+right)>>1;
    BuildTree(left, mid, root << 1);
    BuildTree(mid+1, right, root << 1|1);
}

int query(int w, int left, int right, int root)
{
    if (left == right)
        return 1;

    PushDown(root, right-left+1);

    int mid = (left+right)>>1;
    if (w <= sum[root<<1])
        return query(w, left, mid, root << 1);
    else if (rsum[root<<1] + lsum[root<<1|1] >= w)
        return mid - rsum[root<<1]+1;
    else
        return query(w, mid+1, right, root << 1|1);
}

void UpData(int L, int R, int c, int left, int right, int root)
{
    if (L <= left && right <= R)
    {
        lsum[root] = rsum[root] = sum[root] = c ? 0 : right-left+1;
        sym[root] = c;
        return;
    }

    PushDown(root, right-left+1);

    int mid = (right+left)>>1;
    if (L <= mid)
        UpData(L, R, c, left, mid, root << 1);
    if (mid < R)
        UpData(L, R, c, mid+1, right, root << 1|1);

    PushUp(root, right-left+1);
}

void PushUp(int root, int k)
{
    lsum[root] = lsum[root << 1];
    rsum[root] = rsum[root << 1|1];

    if (lsum[root] == k-(k>>1))
        lsum[root] += lsum[root << 1|1];
    if (rsum[root] == k>>1)
        rsum[root] += rsum[root << 1];

    sum[root] = Max(rsum[root << 1] + lsum[root << 1|1], Max(sum[root << 1], sum[root << 1|1]));
}

void PushDown(int root, int k)
{
    if (sym[root] != -1)
    {
        sym[root << 1] = sym[root << 1|1] = sym[root];
        lsum[root << 1] = rsum[root << 1] = sum[root << 1] = sym[root] ? 0:(k-(k>>1));
        lsum[root << 1|1] = rsum[root << 1|1] = sum[root << 1|1] = sym[root] ? 0:(k>>1);
        sym[root] = -1;
    }
}


版权声明:Designed by Sureina 2016©Copyright.All Right Reserved

POJ3667-Hotel-线段树区间合并(模板)

题目链接:http://poj.org/problem?id=3667 线段树真是牛逼啊,这么多的功能。。。 这是个线段树维护区间合并的问题;我们要维护一个区间的从左端点开始的最长区间,右端点的最...
  • wlxsq
  • wlxsq
  • 2015年08月06日 09:52
  • 840

POJ 3667 hotel 和 NYOJ 537 hotel 【线段树之区间合并】

原题连接:http://poj.org/problem?id=3667 题意:参考样例,第一行输入n,m ,n代表有n个房间,编号为1---n,开始都为空房,m表示以下有m行操作,以下 每行先输入一...
  • PIAOYI0208
  • PIAOYI0208
  • 2012年11月05日 18:58
  • 3616

poj 3667Hotel(经典线段树)

题目大意: 有N个房间排在一列,有两种操作。 1:查询最靠左的长度为len的空房间,并且入住这些空房间。 2:以l开头,长度为r的房间退房。(如果本来就是空的 还是要退房)。...
  • tsxhl111
  • tsxhl111
  • 2014年11月12日 15:41
  • 546

线段树专题—POJ 3667 Hotel(区间合并模板)

题意:给一个n和m,表示n个房间,m次操作,操作类型有2种,一种把求连续未租出的房间数有d个的最小的最左边的房间号,另一个操作时把从x到x+d-1的房间号收回。 分析:这是一个区间合并的典型...
  • sin_XF
  • sin_XF
  • 2015年08月15日 14:47
  • 761

【POJ】3667-Hotel(线段树的区间合并)

标记线段树的时候利用 lsum rsum msum 记录最左边 zui右边 以及整个区间的最大连续空位的值 维护的时候注意合并#include #include #include using nam...
  • u013451221
  • u013451221
  • 2015年04月27日 16:02
  • 620

poj 3667 Hotel(线段树)

poj 3667 Hotel 题目大意:给定一个区间,两种操作: 1 x:找到区间中最左边,将长度为x的区间放入,要求尽量靠左。2 l r:清空l,r + l - 1这段区间。 解题...
  • u011328934
  • u011328934
  • 2014年09月28日 10:18
  • 474

POJ - 3667 Hotel

POJ - 3667  Hotel The cows are journeying north to Thunder Bay in Canada to gain cultural enrichmen...
  • kele52he
  • kele52he
  • 2017年07月04日 21:33
  • 125

【线段树】 POJ 3667 Hotel

这道题和那道HDOJ 3308 LCIS
  • blankcqk
  • blankcqk
  • 2014年06月20日 20:47
  • 209

POJ 3667 Hotel 线段树

用lmax记录从最左端边起的最长线段,rmax记录从最右端起的最长线段,max记录整条线段中最长的线段,tag=-1表示无需更新,0表示空房间,1表示满房间 由于1和l很像,找了很久才发现我query...
  • zhengweijian15
  • zhengweijian15
  • 2014年02月21日 16:25
  • 316

POJ 3667 Hotel (线段树)

题目类型  线段树 题目意思 给出最多50000个房间 最多有50000个操作 操作1 安排x个连续的空房间 (尽量安排靠前的,如果不能安排输出0) 并输出安排的第1个房间的编号...
  • Yunyouxi
  • Yunyouxi
  • 2014年12月01日 22:28
  • 291
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ 3667 - Hotel
举报原因:
原因补充:

(最多只允许输入30个字)