poj 3667 hotel

来源:互联网 发布:mac五国问题 编辑:程序博客网 时间:2024/06/18 13:03

Hotel
Time Limit: 3000MS Memory Limit: 65536KTotal Submissions: 17272 Accepted: 7486

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 groupi 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 roomsXi ..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 61 31 31 31 32 5 51 6

Sample Output

14705

Source


题意:

n个房间,m个操作

1 a 表示 a个人要入住,房间必须是连续的,问能住到的最小号从几开始

2 a b 表示 从a号房间开始的b个人要退房


解题思路

什么都不说了。心累。。。代码注释很清楚

代码

#include <iostream>#include <cstdio>#include <map>#include <cmath>#include <string.h>#include <algorithm>#include <set>#include <sstream>#include <vector>#include <queue>#include <stack>using namespace std;const int maxn = 55555*4;const int INF = 0x3f3f3f3f;struct node{    int l,r;    int op;///延迟标记,-1表示没标记,1表示住进人,0表示退房    int lsum,rsum,msum;///从左边开始连续的房间数,从右边开始连续的房间数,最大的连续房间数}tree[maxn];void buildtree(int node,int b,int e){    int mid = (b+e)/2;    tree[node].l = b;    tree[node].r  = e;    tree[node].op = -1;    tree[node].lsum = tree[node].rsum = tree[node].msum = e-b+1;    if(b==e) return;    if(b <= mid) buildtree(node*2,b,mid);    if(e > mid) buildtree(node*2+1,mid+1,e);}void pushDown(int node){    if(tree[node].op == -1)  return; ///这个区间没有任何改动    tree[node*2].op = tree[node*2+1].op = tree[node].op;    if(tree[node].op == 1){///要住人        tree[node*2].lsum = tree[node*2].rsum = tree[node*2].msum = 0;        tree[node*2+1].lsum = tree[node*2+1].rsum = tree[node*2+1].msum = 0;    }    else{        tree[node*2].lsum = tree[node*2].rsum = tree[node*2].msum = tree[node*2].r - tree[node*2].l+1;        tree[node*2+1].lsum = tree[node*2+1].rsum = tree[node*2+1].msum = tree[node*2+1].r - tree[node*2+1].l+1;    }    tree[node].op = -1;///完成任务,取消标记}void pushUp(int node){    tree[node].lsum = tree[node*2].lsum;    tree[node].rsum = tree[node*2+1].rsum;    if(tree[node].lsum == tree[node*2].r - tree[node*2].l + 1)///如果左边最大完全等于左儿子的区间长度        tree[node].lsum += tree[node*2+1].lsum;///右儿子的左边可能有空位    if(tree[node].rsum == tree[node*2+1].r - tree[node*2+1].l + 1)        tree[node].rsum += tree[node*2].rsum;    ///这个区间的最大空房间数可能是从左或右开始的连续空房间数    ///也可能是中间连续的空房间数    tree[node].msum = max(tree[node*2].msum,tree[node*2+1].msum);///这里注意是左右俩儿子的最大中取最大    tree[node].msum = max(tree[node].msum,tree[node*2].rsum + tree[node*2+1].lsum);}void update(int node,int ql,int qr,int mark){    if(ql <= tree[node].l && qr >= tree[node].r){        tree[node].op = mark;        if(mark == 1){///要住人            tree[node].lsum = tree[node].rsum = tree[node].msum = 0;        }        else{///要搬走            tree[node].lsum = tree[node].rsum = tree[node].msum = tree[node].r - tree[node].l + 1;        }        return ;    }    ///要用的他左右儿子的相关信息了,所以需要将曾经进行的操作传下去    pushDown(node);    int mid = (tree[node].l+tree[node].r)/2;    if(ql <= mid) update(node*2,ql,qr,mark);    if(mid < qr) update(node*2+1,ql,qr,mark);    pushUp(node);}int query(int node, int w){    if(tree[node].l == tree[node].r) return tree[node].l;    ///要用的他左右儿子的相关信息了,所以需要将曾经进行的操作传下去    pushDown(node);    if(tree[node*2].msum >= w) return query(node*2,w);    else if(tree[node*2].rsum + tree[node*2+1].lsum >= w){        return tree[node*2].r - tree[node*2].rsum +1;///右区间 - 右连续0的个数 + 1 = 第一个人住的房间号    }   /// else    return query(node*2+1,w);}int main(){    int n,m;    scanf("%d%d",&n,&m);    buildtree(1,1,n);    while(m--){        int c,a,b;        scanf("%d",&c);        if(c==1){///住人            scanf("%d",&a);            if(tree[1].msum < a) printf("0\n");            else{                int ans = query(1,a);                printf("%d\n",ans);                update(1,ans,ans+a-1,1);            }        }        else{///退房            scanf("%d%d",&a,&b);            update(1,a,a+b-1,0);        }    }    return 0;}



1 0
原创粉丝点击