zoukankan      html  css  js  c++  java
  • 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;
    } 
    

      

  • 相关阅读:
    获取指定扩展名的文件 分类: python 小练习 20130514 16:06 229人阅读 评论(0) 收藏
    #遍历E盘下的mp3文件 分类: python 小练习 python 20130514 18:27 303人阅读 评论(0) 收藏
    🍖Linux输出重定向
    🍖手动添加用户
    🍗文件权限管理
    🍖文件管理之打包压缩
    🍖文件处理三剑客:sed awk grep
    🍖权限管理之用户与用户组
    🍖文件管理之字符处理 sort uniq cut tr wc
    🍖文件处理之上传下载
  • 原文地址:https://www.cnblogs.com/handsomecui/p/5202413.html
Copyright © 2011-2022 走看看