poj 3667 hotel

来源:互联网 发布:苹果电脑安装软件 编辑:程序博客网 时间:2024/05/01 12:56

Hotel
Time Limit: 3000MS Memory Limit: 65536KTotal Submissions: 15167 Accepted: 6565

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 D(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 61 31 31 31 32 5 51 6

Sample Output

14705

Source

USACO 2008 February Gold

题目大意:用N个连续的旅馆房间。m个操作,操作分两种。

先读入x, x==1 表示有一个旅行团要入住,他们需要连续的y个房间,并且要求开始的房间号尽量小,如果无法满足条件就输出0;

x==2 表示从房间y开始有连续z个旅客离开旅馆。

针对每一个操作1,输出最靠前的房间号。

题解:线段树维护区间。

刚看到这道题的时候真是无从下手,都有一头撞死在电脑上的冲动了.后来经过zyf神犇的指点,领悟到了一些门道。

这道题针对每个区间需要维护三个值tr[x]表示当前区间中最长的连续房间数,ls[x]表示从区间的开始最长的连续房间数,rs[x]表示从区间末尾最长的连续房间数。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define N 60000using namespace std;int n,m;int tr[N*4],ls[N*4],rs[N*4],delta[N*4];void update(int x){  ls[x]=rs[x]=tr[x]=tr[x<<1]+tr[x<<1|1];//初始化}void build(int now,int l,int r)//建树{  if (l==r)   {    tr[now]=1; ls[now]=1; rs[now]=1; return;   }  int mid=(l+r)/2;  build(now<<1,l,mid);  build(now<<1|1,mid+1,r);  update(now);}void pushdown(int x,int l,int r)//标记下放{  if (!delta[x]) return ;  int mid=(l+r)/2;  if (!tr[x])   tr[x<<1]=ls[x<<1]=rs[x<<1]=tr[x];  else   tr[x<<1]=ls[x<<1]=rs[x<<1]=mid-l+1;  if (!tr[x])   tr[x<<1|1]=ls[x<<1|1]=rs[x<<1|1]=tr[x];  else   tr[x<<1|1]=ls[x<<1|1]=rs[x<<1|1]=r-mid;  delta[x<<1]=delta[x<<1|1]=1;  delta[x]=0;}int find(int now,int l,int r,int len){  if (l==r) return l;  pushdown(now,l,r);  int mid=(l+r)/2;  if (tr[now<<1]>=len)//因为要求房间号尽可能小,所以如果左半部分有满足条件的答案,那么就向左半部分搜寻   return find(now<<1,l,mid,len);  else   if (rs[now<<1]+ls[now<<1|1]>=len)//如果左半部分无法满足,而左半部分的末尾与右半部分的开头可以构成一个合法答案的话,就从左半部分选取尽可能多的房间,即rs[now<<1]    return mid-rs[now<<1]+1;   else    return find(now<<1|1,mid+1,r,len);//最后在从右半部寻找答案}void update1(int x,int l,int r){  int mid=(l+r)/2;  tr[x]=max(max(tr[x<<1],tr[x<<1|1]),rs[x<<1]+ls[x<<1|1]);//最大值有三种可能,全部在左半部分,全部在右半部分,和横跨两部分  ls[x]=ls[x<<1]+(ls[x<<1]==mid-l+1?ls[x<<1|1]:0);//在更新这里时要格外注意,当前区间的ls[x]不一定等于ls[x<<1]有可能还包含ls[x<<1|1]的一部分  rs[x]=rs[x<<1|1]+(rs[x<<1|1]==r-mid?rs[x<<1]:0);//rs[x]也是同理}void qjchange(int now,int l,int r,int ll,int rr,int k)//与线段上一般的区间修改几乎相同,标记k==0表示占用房间,k==1表示清理出空房间,最后不要忘记更新当前区间的最值{ if(l>=ll&&r<=rr)  {  if (k==0)   tr[now]=ls[now]=rs[now]=0;  else   tr[now]=ls[now]=rs[now]=r-l+1;  delta[now]=1;   return;  } pushdown(now,l,r); int mid=(l+r)/2; if (ll<=mid)  qjchange(now<<1,l,mid,ll,rr,k); if (rr>mid)  qjchange(now<<1|1,mid+1,r,ll,rr,k); update1(now,l,r);}int main(){  scanf("%d%d",&n,&m);  build(1,1,n);  for (int i=1;i<=m;i++)  {   int x,y,z; scanf("%d",&x);   if (x==1)    {      scanf("%d",&y);      if (tr[1]<y)       printf("0\n");      else      {       int k=find(1,1,n,y);       printf("%d\n",k);       qjchange(1,1,n,k,k+y-1,0);      }    }   else    {      scanf("%d%d",&y,&z);      qjchange(1,1,n,y,y+z-1,1);    }  }}









0 0
原创粉丝点击