Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 17272 | Accepted: 7486 |
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
Source
题意:
n个房间,m个操作
1 a 表示 a个人要入住,房间必须是连续的,问能住到的最小号从几开始
2 a b 表示 从a号房间开始的b个人要退房
解题思路
什么都不说了。心累。。。代码注释很清楚
代码
#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
#include <string.h>
#include <algorithm>
#include <set>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
const int maxn = 55555*4;
const int INF = 0x3f3f3f3f;
struct node{
int l,r;
int op;///延迟标记,-1表示没标记,1表示住进人,0表示退房
int lsum,rsum,msum;///从左边开始连续的房间数,从右边开始连续的房间数,最大的连续房间数
}tree[maxn];
void buildtree(int node,int b,int e){
int mid = (b+e)/2;
tree[node].l = b;
tree[node].r = e;
tree[node].op = -1;
tree[node].lsum = tree[node].rsum = tree[node].msum = e-b+1;
if(b==e) return;
if(b <= mid) buildtree(node*2,b,mid);
if(e > mid) buildtree(node*2+1,mid+1,e);
}
void pushDown(int node){
if(tree[node].op == -1) return; ///这个区间没有任何改动
tree[node*2].op = tree[node*2+1].op = tree[node].op;
if(tree[node].op == 1){///要住人
tree[node*2].lsum = tree[node*2].rsum = tree[node*2].msum = 0;
tree[node*2+1].lsum = tree[node*2+1].rsum = tree[node*2+1].msum = 0;
}
else{
tree[node*2].lsum = tree[node*2].rsum = tree[node*2].msum = tree[node*2].r - tree[node*2].l+1;
tree[node*2+1].lsum = tree[node*2+1].rsum = tree[node*2+1].msum = tree[node*2+1].r - tree[node*2+1].l+1;
}
tree[node].op = -1;///完成任务,取消标记
}
void pushUp(int node){
tree[node].lsum = tree[node*2].lsum;
tree[node].rsum = tree[node*2+1].rsum;
if(tree[node].lsum == tree[node*2].r - tree[node*2].l + 1)///如果左边最大完全等于左儿子的区间长度
tree[node].lsum += tree[node*2+1].lsum;///右儿子的左边可能有空位
if(tree[node].rsum == tree[node*2+1].r - tree[node*2+1].l + 1)
tree[node].rsum += tree[node*2].rsum;
///这个区间的最大空房间数可能是从左或右开始的连续空房间数
///也可能是中间连续的空房间数
tree[node].msum = max(tree[node*2].msum,tree[node*2+1].msum);///这里注意是左右俩儿子的最大中取最大
tree[node].msum = max(tree[node].msum,tree[node*2].rsum + tree[node*2+1].lsum);
}
void update(int node,int ql,int qr,int mark){
if(ql <= tree[node].l && qr >= tree[node].r){
tree[node].op = mark;
if(mark == 1){///要住人
tree[node].lsum = tree[node].rsum = tree[node].msum = 0;
}
else{///要搬走
tree[node].lsum = tree[node].rsum = tree[node].msum = tree[node].r - tree[node].l + 1;
}
return ;
}
///要用的他左右儿子的相关信息了,所以需要将曾经进行的操作传下去
pushDown(node);
int mid = (tree[node].l+tree[node].r)/2;
if(ql <= mid) update(node*2,ql,qr,mark);
if(mid < qr) update(node*2+1,ql,qr,mark);
pushUp(node);
}
int query(int node, int w){
if(tree[node].l == tree[node].r) return tree[node].l;
///要用的他左右儿子的相关信息了,所以需要将曾经进行的操作传下去
pushDown(node);
if(tree[node*2].msum >= w) return query(node*2,w);
else if(tree[node*2].rsum + tree[node*2+1].lsum >= w){
return tree[node*2].r - tree[node*2].rsum +1;///右区间 - 右连续0的个数 + 1 = 第一个人住的房间号
}
/// else
return query(node*2+1,w);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
buildtree(1,1,n);
while(m--){
int c,a,b;
scanf("%d",&c);
if(c==1){///住人
scanf("%d",&a);
if(tree[1].msum < a) printf("0\n");
else{
int ans = query(1,a);
printf("%d\n",ans);
update(1,ans,ans+a-1,1);
}
}
else{///退房
scanf("%d%d",&a,&b);
update(1,a,a+b-1,0);
}
}
return 0;
}