1. 程式人生 > >1593: [Usaco2008 Feb]Hotel 旅館 (線段樹)

1593: [Usaco2008 Feb]Hotel 旅館 (線段樹)

arch submit play 連續 open 判斷 else 每一個 奶牛

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 旅館 (線段樹)