您的位置:首页 > 其它

poj 3667 hotel 旅馆(线段树)

2017-06-10 18:40 405 查看

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: