1593: [Usaco2008 Feb]Hotel 旅馆 (线段树)

Posted 心之所向 素履以往

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1593: [Usaco2008 Feb]Hotel 旅馆 (线段树)相关的知识,希望对你有一定的参考价值。

1593: [Usaco2008 Feb]Hotel 旅馆

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 451  Solved: 262
[Submit][Status][Discuss]

Description

奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及明媚的阳光。作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿。这个巨大的旅馆一共有N (1 <= N <= 50,000)间客房,它们在同一层楼中顺次一字排开,在任何一个房间里,只需要拉开窗帘,就能见到波光粼粼的湖面。 贝茜一行,以及其他慕名而来的旅游者,都是一批批地来到旅馆的服务台,希望能订到D_i (1 <= D_i <= N)间连续的房间。服务台的接待工作也很简单:如果存在r满足编号为r..r+D_i-1的房间均空着,他就将这一批顾客安排到这些房间入住;如果没有满足条件的r,他会道歉说没有足够的空房间,请顾客们另找一家宾馆。如果有多个满足条件的r,服务员会选择其中最小的一个。 旅馆中的退房服务也是批量进行的。每一个退房请求由2个数字X_i、D_i 描述,表示编号为X_i..X_i+D_i-1 (1 <= X_i <= N-D_i+1)房间中的客人全部离开。退房前,请求退掉的房间中的一些,甚至是所有,可能本来就无人入住。 而你的工作,就是写一个程序,帮服务员为旅客安排房间。你的程序一共需要处理M (1 <= M < 50,000)个按输入次序到来的住店或退房的请求。第一个请求到来前,旅店中所有房间都是空闲的。 

Input

* 第1行: 2个用空格隔开的整数:N、M 

* 第2..M+1行: 第i+1描述了第i个请求,如果它是一个订房请求,则用2个数字 1、D_i描述,数字间用空格隔开;如果它是一个退房请求,用3 个以空格隔开的数字2、X_i、D_i描述

Output

* 第1..??行: 对于每个订房请求,输出1个独占1行的数字:如果请求能被满足 ,输出满足条件的最小的r;如果请求无法被满足,输出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

HINT

 

Source

Gold

 

技术分享
  1 /*
  2     建一颗线段树 
  3     储存四个信息 lm 代表从区间左端点开始向右连续最长为空的序列长度
  4                  rm 代表从区间右端点开始向左连续最长为空的序列长度
  5                  m  代表区间内连续最长为空的序列长度
  6                  s  代表区间长度 
  7     维护 前三个信息 
  8     用 s 判断区间是否可用 从而更新 lm rm 和 m 
  9     具体看操作 
 10 */
 11 #include<cstdio>
 12 #include<iostream>
 13 #define MAXN 100010
 14 
 15 using namespace std;
 16 
 17 struct de {
 18     int l,r;
 19     int s,lm,rm,m;
 20     int tag;
 21 };
 22 de tr[MAXN<<2];
 23 
 24 int n,T,opt,x,y;
 25 
 26 inline void read(int&x) { 
 27     int f=1;x=0;char c=getchar(); 
 28     while(c>9||c<0) {if(c==-) f=-1;c=getchar();} 
 29     while(c>=0&&c<=9) {x=(x<<1)+(x<<3)+c-48;c=getchar();} 
 30     x=x*f; 
 31 } 
 32 
 33 inline void up(int now) {
 34     if(tr[now<<1].m==tr[now<<1].s) tr[now].lm=tr[now<<1].m+tr[now*2+1].lm;
 35     else tr[now].lm=tr[now<<1].lm;
 36     if(tr[now*2+1].m==tr[now*2+1].s) tr[now].rm=tr[now*2+1].m+tr[now<<1].rm;
 37     else tr[now].rm=tr[now*2+1].rm;
 38     tr[now].m=max(max(tr[now<<1].m,tr[now*2+1].m),tr[now<<1].rm+tr[now*2+1].lm);
 39     return;
 40 }
 41 
 42 inline void down(int now) {
 43     if(tr[now].tag==1) {
 44         tr[now<<1].tag=tr[now*2+1].tag=tr[now].tag;
 45         tr[now<<1].lm=tr[now<<1].rm=tr[now<<1].m=0;
 46         tr[now*2+1].lm=tr[now*2+1].m=tr[now*2+1].rm=0;
 47     }
 48     if(tr[now].tag==2) {
 49         tr[now<<1].tag=tr[now*2+1].tag=tr[now].tag;
 50         tr[now<<1].lm=tr[now<<1].rm=tr[now<<1].m=tr[now<<1].s;
 51         tr[now*2+1].lm=tr[now*2+1].m=tr[now*2+1].rm=tr[now*2+1].s;
 52     }
 53     tr[now].tag=0;
 54 }
 55 
 56 void build_tree(int now,int l,int r) {
 57     tr[now].l=l;tr[now].r=r;
 58     tr[now].lm=tr[now].rm=tr[now].m=tr[now].s=r-l+1;
 59     if(l==r) return;
 60     int mid=(l+r)>>1;
 61     build_tree(now<<1,l,mid);
 62     build_tree(now*2+1,mid+1,r);
 63     return;
 64 }
 65 
 66 int query(int now,int l,int r,int len) {
 67     if(tr[now].l==tr[now].r) return l;
 68     if(tr[now].tag) down(now);
 69     int mid=(tr[now].l+tr[now].r)>>1;
 70     if(tr[now<<1].m>=len) return query(now<<1,l,r,len);
 71     if(tr[now<<1].rm+tr[now*2+1].lm>=len) return mid-tr[now<<1].rm+1;
 72     else return query(now*2+1,mid+1,r,len);
 73 }
 74 
 75 void modify(int now,int l,int r,int d) {
 76     if(l<=tr[now].l&&r>=tr[now].r) {
 77         if(d==1) tr[now].lm=tr[now].rm=tr[now].m=0;
 78         else tr[now].lm=tr[now].rm=tr[now].m=tr[now].s;
 79         tr[now].tag=d;
 80         return;
 81     }
 82     if(tr[now].tag) down(now);
 83     int mid=(tr[now].l+tr[now].r)>>1;
 84     if(l<=mid) modify(now<<1,l,r,d);
 85     if(r>mid) modify(now*2+1,l,r,d);
 86     up(now);
 87 }
 88 
 89 int main() {
 90     read(n);read(T);
 91     build_tree(1,1,n);
 92     while(T--) {
 93         read(opt);
 94         if(opt==1) {
 95             read(x);
 96             if(tr[1].m<x) {printf("0\n");continue;}
 97             int pos=query(1,1,n,x);
 98             printf("%d\n",pos);
 99             modify(1,pos,pos+x-1,1);
100         }
101         else {
102             read(x);read(y);
103             modify(1,x,y+x-1,2);
104         }
105     }
106     return 0;
107 }
题解

 

以上是关于1593: [Usaco2008 Feb]Hotel 旅馆 (线段树)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1593 [Usaco2008 Feb]Hotel 旅馆

[BZOJ1593][Usaco2008 Feb]Hotel 旅馆

BZOJ1593: [Usaco2008 Feb]Hotel 旅馆

poj3667(bzoj1593)--Usaco08Feb Hotel--线段树区间合并

USACO 2008 FEB Eating Together

bzoj 1611 [Usaco2008 Feb]Meteor Shower流星雨 bfs