POJ 3667 Hotel
2016-07-28 15:06
417 查看
Time Limit: 3000MS Memory Limit: 65536K
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 ≤ 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
【题意】 一个旅馆有N个房间,现有M条指令,指令分两个类型,以1开头的是查询操作,以2开头的是更新操作;
1 X 表示在总区间内查询一个长度为X的空房间,并且要最靠左,能找到的话返回这个区间的左端点并占用了这个区间,找不到返回0;
2 Xi Di , 表示从单位Xi开始,清除一段长度为Di的区间(就是退房),不需要输出。
【解题思路】 此题用线段树做,该题主要是两个操作,更新操作和查询操作;更新操作相对简单一点,用一个标记记录房间是否入住,在通过向下传递标记和返回值来更新每个节点的lsum(左最大连续区间),rsum(右最大连续区间),nsum(最大连续区间);查询要输出区间的具体位置,则有:
1.如果左子区间的nsum不小于X,查询左子区间;
2.若左子区间的rsum加上右子区间的lsum不小于X,直接返回tr[id*2].r-tr[id*2].rsum+1,注意,不需要再递归;
3.若右子区间的nsum不小于X,查询右子区间;
4.若都不符合,则返回0;
【AC代码】
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 ≤ 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
【题意】 一个旅馆有N个房间,现有M条指令,指令分两个类型,以1开头的是查询操作,以2开头的是更新操作;
1 X 表示在总区间内查询一个长度为X的空房间,并且要最靠左,能找到的话返回这个区间的左端点并占用了这个区间,找不到返回0;
2 Xi Di , 表示从单位Xi开始,清除一段长度为Di的区间(就是退房),不需要输出。
【解题思路】 此题用线段树做,该题主要是两个操作,更新操作和查询操作;更新操作相对简单一点,用一个标记记录房间是否入住,在通过向下传递标记和返回值来更新每个节点的lsum(左最大连续区间),rsum(右最大连续区间),nsum(最大连续区间);查询要输出区间的具体位置,则有:
1.如果左子区间的nsum不小于X,查询左子区间;
2.若左子区间的rsum加上右子区间的lsum不小于X,直接返回tr[id*2].r-tr[id*2].rsum+1,注意,不需要再递归;
3.若右子区间的nsum不小于X,查询右子区间;
4.若都不符合,则返回0;
【AC代码】
#include<stdio.h> #include<algorithm> #define fff 50005 using namespace std; struct node { int l,r,vis; int lsum,rsum,nsum; }tr[fff*4]; void pushdown(int id) { if(tr[id].vis!=-1) { tr[id*2].vis=tr[id*2+1].vis=tr[id].vis; tr[id*2].lsum=tr[id*2].rsum=tr[id*2].nsum=(tr[id].vis?0:tr[id*2].r-tr[id*2].l+1); tr[id*2+1].lsum=tr[id*2+1].rsum=tr[id*2+1].nsum=(tr[id].vis?0:tr[id*2+1].r-tr[id*2+1].l+1); tr[id].vis=-1; } } void pushup(int id) { tr[id].lsum=tr[id*2].lsum; tr[id].rsum=tr[id*2+1].rsum; tr[id].nsum=max(tr[id*2].rsum+tr[id*2+1].lsum,max(tr[id*2].nsum,tr[id*2+1].nsum)); if(tr[id*2].lsum==tr[id*2].r-tr[id*2].l+1) tr[id].lsum=tr[id*2].lsum+tr[id*2+1].lsum; if(tr[id*2+1].rsum==tr[id*2+1].r-tr[id*2+1].l+1) tr[id].rsum=tr[id*2+1].rsum+tr[id*2].rsum; } void build(int id,int l,int r) { tr[id].l=l;tr[id].r=r; tr[id].lsum=tr[id].rsum=tr[id].nsum=r-l+1; tr[id].vis=-1; //初始化为-1,入住和退房都可以对线段树进行更新 if(l==r) return; int mid=(l+r)/2; build(id*2,l,mid); build(id*2+1,mid+1,r); } void update(int id,int l,int r,int x) { if(tr[id].l==l&&tr[id].r==r) { tr[id].vis=x; tr[id].lsum=tr[id].rsum=tr[id].nsum=(x?0:tr[id].r-tr[id].l+1); return; } pushdown(id); int mid=(tr[id].l+tr[id].r)/2; if(r<=mid) update(id*2,l,r,x); else if(l>mid) update(id*2+1,l,r,x); else { update(id*2,l,mid,x); update(id*2+1,mid+1,r,x); } pushup(id); } int found(int id,int len) { pushdown(id); //因为要输出最左区间的位置,下面的判断顺序不可以随便调换,必须是从左到右 if(tr[id*2].nsum>=len) return found(id*2,len); else if(tr[id*2].rsum+tr[id*2+1].lsum>=len) return tr[id*2].r-tr[id*2].rsum+1; //排除了左子区间的情况,可以直接返回该区间的位置 else if(tr[id*2+1].nsum>=len) return found(id*2+1,len); else return 0; } int main() { int n,m,x,y,z; while(scanf("%d%d",&n,&m)!=EOF) { build(1,1,n); while(m--) { scanf("%d",&x); if(x==1) { scanf("%d",&y); int k=found(1,y); printf("%d\n",k); if(k) //注意,当输出是0的时候,没有人入住,不需要更新 update(1,k,k+y-1,1); } else { scanf("%d%d",&y,&z); update(1,y,y+z-1,0); } } } return 0; }
相关文章推荐
- nginx架构初探
- 《挑战编程:程序设计竞赛训练手册》
- thinkpad L440关闭触摸屏
- closest() 方法 与.parents()方法
- Android---优化下载让网络访问更高效(三)
- Hacker学习发展流程图 V1.0 (转)
- STL heap usage
- linux基础(9)-获取时间
- AngularJS中实现动画效果的方法
- Android---优化下载让网络访问更高效(二)
- 单链表的整表创建
- 播放和录制音频
- HDU1275DP
- 如何做一个基于ASP.NET MVC 网站(五)
- Mybatis中mapper代理方法替换原始Dao开发方法
- XPath学习笔记
- 断点续传
- hdu 1016 Prime Ring Problem(dfs,素数环)
- Java native 方法
- 将master分支内容合并到dev分支