Hotel(线段树合并)

Hotel
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 14958   Accepted: 6450

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
题解:
Hotel有N(1 ≤ N ≤ 50,000)间rooms,并且所有的rooms都是连续排列在同一边,groups需要check in 房间,
要求房间的编号为连续的r..r+Di-1并且r是最小的;visitors同样可能check out,
并且他们每次check out都是编号为Xi ..Xi +Di-1 (1 ≤ XiN-Di+1)的房间,题目的输入有两种样式:
  1. 1  a     :  groups需要check in  a间编号连续的房间
  2. 2  a   b : visitors  check out 房间,其中房间编号是 a…a+b-1

要求对于每次request,输出为groups分配数目为a的房间中编号最小的房间编号


利用线段树建立模型,维护最大连续区间长度,其中区间长度就是对应的房间数目,并且对应区间中最左边的断点就是answer,
同时因为需要求出连续区间的最大长度,因此每次PushUp时都将左右区间合并,
lsum维护左区间的最大长度,rsum维护右区间的最大长度,sum维护区间1…N中的最大连续区间长度,lazy延迟标记;
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int INF=0x3f3f3f3f;
#define mem(x,y) memset(x,y,sizeof(x))
#define SI(x) scanf("%d",&x)
#define PI(x) printf("%d",x)
#define SD(x,y) scanf("%lf%lf",&x,&y)
#define P_ printf(" ")
#define ll root<<1
#define rr root<<1|1
#define lson ll,l,mid
#define rson rr,mid+1,r
typedef long long LL;
const int MAXN=50010<<2;
int sum[MAXN],lsum[MAXN],rsum[MAXN];
int lazy[MAXN];
void pushdown(int root,int v){
	if(lazy[root]!=-1){
		lazy[ll]=lazy[rr]=lazy[root];
		sum[ll]=lsum[ll]=rsum[ll]=lazy[root]?0:v-(v>>1);
		sum[rr]=lsum[rr]=rsum[rr]=lazy[root]?0:v>>1;
		lazy[root]=-1;
	}
}
void pushup(int root,int v){
	lsum[root]=lsum[ll];
	rsum[root]=rsum[rr];
	if(lsum[root]==v-(v>>1))lsum[root]+=lsum[rr];
	if(rsum[root]==(v>>1))rsum[root]+=rsum[ll];
	sum[root]=max(lsum[rr]+rsum[ll],max(sum[ll],sum[rr]));
}
void build(int root,int l,int r){
	int mid=(l+r)>>1;
	sum[root]=lsum[root]=rsum[root]=r-l+1;
	lazy[MAXN]=-1;
	if(l==r)return;
	build(lson);
	build(rson); 
}
void update(int root,int l,int r,int A,int B,int c){
	if(l>=A&&r<=B){
		lazy[root]=c;
		sum[root]=lsum[root]=rsum[root]=c?0:r-l+1;
		return;
	}
	pushdown(root,r-l+1);
	int mid=(l+r)>>1;
	if(mid>=A)update(lson,A,B,c);
	if(mid<B)update(rson,A,B,c);
	pushup(root,r-l+1);
}
int query(int root,int l,int r,int v){
	if(l==r)return l;
	pushdown(root,r-l+1);
	int mid=(l+r)>>1;
	if(sum[ll]>=v)return query(lson,v);
	else if(lsum[rr]+rsum[ll]>=v)return mid-rsum[ll]+1;
	else return query(rson,v);
}
int main(){
	int N,M;
	while(~scanf("%d%d",&N,&M)){
		build(1,1,N);
		int a,b,c;
		while(M--){
			SI(a);SI(b);
			if(a==1){
				if(sum[1]<b){
					puts("0");continue;
				}
				int ans=query(1,1,N,b);
				printf("%d
",ans);
				update(1,1,N,ans,ans+b-1,1);//询问完毕需要更新上; 
			}
			else{
				SI(c);
				update(1,1,N,b,b+c-1,0);
			}
		}
	}
	return 0;
} 

  

原文地址:https://www.cnblogs.com/handsomecui/p/5202413.html