poj 3667 hotel 旅馆(线段树)

poj 3667 hotel 旅馆

【问题描述】
OIER们最近的旅游计划,是到长春净月潭,享受那里的湖光山色,以及明媚的阳光。你作为整个旅游的策划者和负责人,选择在潭边的一家著名的旅馆住宿。这个巨大的旅馆一共有N (1 <= N <= 50000)间客房,它们在同一层楼中顺次一字排开,在任何一个房间里,只需要拉开窗帘,就能见到波光粼粼的潭面。
所有的旅游者,都是一批批地来到旅馆的服务台,希望能订到Di (1 <= Di <= N)间连续的房间。服务台的接待工作也很简单:如果存在r满足编号为r..r+Di-1的房间均空着,他就将这一批顾客安排到这些房间入住;如果没有满足条件的r,他会道歉说没有足够的空房间,请顾客们另找一家宾馆。如果有多个满足条件的r,服务员会选择其中最小的一个。
旅馆中的退房服务也是批量进行的。每一个退房请求由2个数字Xi、Di描述,表示编号为Xi..Xi+Di-1 (1 <= Xi <= N-Di+1)房间中的客人全部离开。退房前,请求退掉的房间中的一些,甚至是所有,可能本来就无人入住。
你的工作,就是写一个程序,帮服务员为旅客安排房间。你的程序一共需要处理M (1 <= M <=50000)个按输入次序到来的住店或退房的请求。第一个请求到来前,旅店中所有房间都是空闲的。

【输入格式】
从文件hotel.in中输入数据。
第1行: 2个用空格隔开的整数:N、M
第2..M+1行: 第i+1描述了第i个请求,如果它是一个订房请求,则用2个数字1、Di描述,数字间用空格隔开;如果它是一个退房请求,用3个以空格隔开的数字2、Xi、Di描述。

【输出格式】
输出到文件hotel.out中。
第1..??行: 对于每个订房请求,输出1个独占1行的数字:如果请求能被满足,输出满足条件的最小的r;如果请求无法被满足,输出0。
【样例输入】
10 6
1 3
1 3
1 3
1 3
2 5 5
1 6
【样例输出】
1
4
7
0
5
【数据规模与约定】
对于20%的数据, 1<=N<=100,1<=M<=200
对于100%的数据,1 <= N <= 50000 ,1 <= M <= 50000,数据有梯度。

思路:
线段树题目,只不过要多维护几个域,维护最大连续区间长度,其中区间长度就是对应的房间数目,llen维护左区间的最大长度,rlen维护右区间的最大长度,len维护区间1…N中的最大连续区间长度。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 50005;
int n, m, q, x, y;
struct Node{
    int llen, rlen, len, lazy;//len 最长一段连续区间 
    Node *ls, *rs;
    Node() {
        ls = rs = NULL;
    }
    void pushdown( int lf, int rg ) {
        if ( lazy == 1 || lazy == 0 ) {
            int mid = (lf + rg) >> 1;
            ls->llen = ls->rlen = ls->len = lazy*(mid-lf+1);
            rs->rlen = rs->llen = rs->len = lazy*(rg-mid);
            ls->lazy = rs->lazy = lazy;
            lazy = -1;
        }
    }
    void pushup( int lf, int rg ) {
        int mid = (lf + rg) >> 1;
        llen = ls->llen;
        rlen = rs->rlen;
        if ( llen == (mid-lf+1) ) llen += rs->llen;
        if ( rlen == (rg-mid) ) rlen += ls->rlen;
        len = max(ls->rlen+rs->llen, max(ls->len,rs->len) );
    }
};
Node pool[N * 4], *tail = pool, *root;
Node *build(int lf, int rg) {
    Node *nd = ++tail;
    if ( lf == rg) {
        nd->llen = nd->rlen = nd->len = 1;
        nd->lazy = -1;
    }
    else {
        int mid = (lf + rg) >> 1;
        nd->ls = build(lf, mid);
        nd->rs = build(mid+1, rg);
        nd->llen = nd->rlen = nd->len = nd->ls->llen + nd->rs->llen;
        nd->lazy = -1;
    }
    return nd;
}
int query(Node *nd, int lf, int rg, int len) {
    if ( lf == rg ) return lf;
    nd->pushdown(lf, rg);
    int mid = (lf + rg) >> 1;
    if ( nd->ls->len >= len ) return query(nd->ls, lf, mid, len);
    else if ( nd->ls->rlen + nd->rs->llen >= len ) return mid-nd->ls->rlen+1;
    else return query(nd->rs, mid+1, rg, len);
}
void modify( Node *nd, int lf, int rg, int L, int R, int val ) {
    if ( L <= lf && rg <= R ) {
        nd->llen = nd->rlen = nd->len = val*(rg-lf+1);
        nd->lazy = val;
        return;
    }
    nd->pushdown(lf, rg);
    int mid = (lf + rg) >> 1;
    if ( L <= mid ) modify(nd->ls, lf, mid, L, R, val);
    if ( R > mid ) modify(nd->rs, mid+1, rg, L, R, val);
    nd->pushup(lf, rg);
}
int main() {
    //freopen( "hotel.in","r",stdin );
    //freopen( "hotel.out","w",stdout );
    scanf( "%d%d", &n, &m );
    root = build(1, n);
    for ( int i = 1; i <= m; i++ ) {
        scanf( "%d", &q );
        if ( q == 1 ) {
            scanf( "%d", &x ); int pos;
            if ( root->len < x ) printf( "0\n" );
            else {
                pos = query( root, 1, n, x );
                printf( "%d\n", pos );
                modify( root , 1, n, pos, pos+x-1, 0 );
            }
        }
        else {
            scanf( "%d%d", &x, &y );
            modify( root, 1, n, x, x+y-1, 1 );
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值