POJ3667 Hotel 线段树

题意:一个旅馆有很多房间,要安排客人住宿。有如下要求:
1、房间排列是线性的(即呈一条线)。
2、每个房间只能住一个人。
3、每来一个团队住宿,只能安排在连续的编号里,且若有多种情况满足条件,开始位置必须尽可能早。
4、若不能住下当前团队,输出0,否则输出起始编号。
思路:拿到这个题目还是毫无思路,不过还好是模板题,就用学长发的模板套了一下。
1、首先建树,我们需要维护三个变量,lmax,rmax,mmax,分别代表从当前区间左侧开始、右侧开始和中间部分最大空余位置数量。为了便于统计剩余数量,我们把房间情况初始化为1 代表有1个空屋。
2、其次更新信息(即客人入住)。因为是区间修改,且数据量不小,所以我们需要lazy标记来延迟更新以减小时间复杂度。
3、最后query函数的作用是用来查询最早满足条件的起点位置。既然最早,所以要从左边开始找合适的嘛,所以是左中右的搜索方式。
另外从代码中可以注意到 只有搜索中间子树的时候是返回的确定值,否则都是返回的调用某个函数。这里很有意思,也是关键代码,可以细细琢磨一下,如下:

		if(t[k<<1].mmax>=len) 
			return query(k<<1,len);//注意这里。。搞清关系!若左子右边界就得加一 不然不用 
        else if(t[k<<1].rmax+t[k<<1|1].lmax>=len) 
        	return (t[k<<1|1].l-t[k<<1].rmax);
        else if(t[k<<1|1].mmax>=len) 
        	return query(k<<1|1,len);
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#define ll long long
#define cl(a,b) memset(a,b,sizeof(a))
#define maxn 50004
using namespace std;
int n,m;
struct node{
    int l,r,lmax,rmax,mmax,lazy;//左侧开始最长 右侧开始最长 中间一块最长
}t[maxn<<2];
void pushup(int k){
    t[k].lmax=t[k<<1].lmax;
    t[k].rmax=t[k<<1|1].rmax;
    if(t[k<<1].lmax==(t[k<<1].r-t[k<<1].l+1)){//若左边满了
        t[k].lmax+=t[k<<1|1].lmax;
    }
    if(t[k<<1|1].rmax==(t[k<<1|1].r-t[k<<1|1].l+1)){
        t[k].rmax+=t[k<<1].rmax;
    }
    t[k].mmax=max(max(t[k<<1].mmax,t[k<<1|1].mmax),t[k<<1].rmax+t[k<<1|1].lmax);
    return;
}
void build(int k,int l,int r){
    t[k].l=l,t[k].r=r,t[k].lazy=-1;//lazy赋值-1
    t[k].lmax=t[k].rmax=t[k].mmax=(r-l+1);
    if(l==r){
        return;
    }else{
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        //pushup(k);//写个正常写法
    }
    return;
}
void pushdown(int k){
    if(t[k].lazy!=-1){
        t[k<<1].mmax=t[k<<1].lmax=t[k<<1].rmax=t[k].lazy*(t[k<<1].r-t[k<<1].l+1);
        t[k<<1|1].mmax=t[k<<1|1].lmax=t[k<<1|1].rmax=t[k].lazy*(t[k<<1|1].r-t[k<<1|1].l+1);
        t[k<<1].lazy=t[k<<1|1].lazy=t[k].lazy;
        t[k].lazy=-1;
    }
}
void updata(int k,int l,int r,int v){//l到r变成v
    if(l<=t[k].l&&t[k].r<=r){//这里没更新全!!! 
        t[k].mmax=t[k].lmax=t[k].rmax=v*(t[k].r-t[k].l+1);
        t[k].lazy=v;
    }else{
        pushdown(k);
        int mid=(t[k].l+t[k].r)>>1;
        if(l<=mid) updata(k<<1,l,r,v);
        if(mid<r) updata(k<<1|1,l,r,v);
        pushup(k);
    }
    return;
}
int query(int k,int len){//查询满足够长度的 最小的坐标
    if(t[k].l==t[k].r){
        return t[k].l;//这里要返回坐标而不是值!zz 
    }else{
        pushdown(k);
        //注意下面,先查询左子树是否符合条件,再查询中间的树,再查询右子树 
        if(t[k<<1].mmax>=len) return query(k<<1,len);//注意这里。。搞清关系!若左子右边界就得加一 不然不用 
        else if(t[k<<1].rmax+t[k<<1|1].lmax>=len) return (t[k<<1|1].l-t[k<<1].rmax);
        else if(t[k<<1|1].mmax>=len) return query(k<<1|1,len);
        return 0;//这里加return 0 是特判所有情况是否能否住下当前group 
    }
}
int main(){
    scanf("%d%d",&n,&m);
    build(1,1,n);
    while(m--){
        int op;
        scanf("%d",&op);
        if(op==1){//入住
            int len;
            scanf("%d",&len);
            int sta=query(1,len);
            if(sta==0){//若住不下 就劝走
                printf("0\n");
            }else{//住下就安排上
                printf("%d\n",sta);
                updata(1,sta,sta+len-1,0);
            }
        }else{//搬出
            int sta,len;
            scanf("%d%d",&sta,&len);
            updata(1,sta,sta+len-1,1);
        }
    }
    return 0;
}
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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值