poj 3667 hotel - 线段树-区间更新-延迟标记

Hotel
Time Limit: 3000MS Memory Limit: 65536K
Total 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 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 ≤ 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 and Di (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 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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值