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; }
相关文章推荐
- POJ 3667 Hotel 线段树 区间合并
- poj 3667 Hotel 经典线段树区间合并
- POJ 3667/BZOJ 1593: [Usaco2008 Feb]Hotel 旅馆
- POJ 3667 Hotel(线段树)
- POJ 3667 Hotel. (线段树 区间合并)
- POJ - 3667 Hotel (线段树 + 区间合并)
- poj(3667)——hotel(线段树区间合并)
- poj 3667 Hotel(线段树,区间合并)
- poj 3667 hotel 线段树成段更新区间合并
- POJ 3667 Hotel【经典的线段树】
- poj 3667 Hotel(线段树)
- POJ 3667 Hotel(线段树:区间覆盖,维护最大连续子区间)
- poj 3667 线段树(Hotel)
- poj 3667 Hotel(线段树 # 7)
- POJ 3667 & 1823 Hotel (线段树区间合并)
- POJ 3667 - Hotel (线段树 区间合并)
- POJ 3667 - Hotel(线段树+区间合并)
- POJ - 3667 Hotel(线段树 区间合并 区间查询)
- poj 3667 Hotel 找最左面连续区间>=need的区间 线段树
- POJ-3667:Hotel(线段树区间合并)