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

相关文章推荐

poj 3667 hotel (线段树+区间合并)

以前学习过的线段树,在查询和更新的基础上加入了区间合并,利用延迟标志来实现这一方法 代码在这: #include #include #include using namespace std;...

POJ 3667 Hotel 线段树(区间合并)

链接:http://poj.org/problem?id=3667 题意:一家旅馆,不断有人入住,退房。入住的人要求房号连续,退房是连续房号的房间退掉。 思路:线段树LAZY-TAG+区间合并。相比于...

POJ 3667 Hotel (线段树求最长连续子序列)

http://poj.org/problem?id=3667题意:有一个线段,从1到n,下面m个操作,操作分两个类型,以1开头的是查询操作,以2开头的是更新操作1 查询操作,找一段长度为W的没被覆盖的...

POJ 3667 Hotel 线段树

Hotel Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 11104 Accep...

Poj 3667 Hotel + Hdu 4553 约会安排 (线段树最左空区间)

题目链接:http://poj.org/problem?id=3667 题意:旅馆的N(1 ≤ n ≤ 50,000) 个房间初始时全为空。现在有M(1 ≤ m (1)1  X,要求得到连续的X...

【POJ 3667】Hotel

POJ 3667题意有n个房间和k个操作,最开始全部为空。操作1:输入一个数d,找出连续d个空房间,输出起点房间编号。若有多个输出最小的,如果不存在输出0。操作2:输入两个数x和d,清空从x开始的d个...
  • Ripped
  • Ripped
  • 2017年02月05日 12:21
  • 116

poj3667 Hotel

经典问题,就是线段树[L, R]上保存3个信息,分别表示以L开头最多连续的空格,R为结尾的最多连续空格,这段区间最大的连续空格。然后就可以写代码了。 (为什么我的线段树这么丑) #include us...

poj3667 Hotel(成段更新+区间合并)

http://poj.org/problem?id=3667 题意:给你n个房间,m种操作,1操作为查看有没有连续长度为num的房间,若有,则返回其左端点,并将其置为非空;2操作为置空st~st...

poj3667_Hotel—线段树区间合并

因为用的都是 int64 所以时间没有那么短,换成int的话应该会小于400ms,该方法应该是时间效率最高的方法,理论上比HH的方法快,任何独立操作都在logn时间完成,而且还有优化~ #inclu...
  • zz_1215
  • zz_1215
  • 2011年10月22日 09:19
  • 388

poj 3667 Hotel(线段树区间分配)

Hotel Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 9550   Accepted...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ 3667 - Hotel
举报原因:
原因补充:

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