NKOI 1550 旅馆
【Usaco Feb08 Gold】旅館
Time Limit:10000MS? Memory Limit:65536K
Total Submit:128 Accepted:71?
Case Time Limit:1000MS
Description
奶牛們最近的旅游計劃,是到蘇必利爾湖畔,享受那里的湖光山色,以及明媚的陽光。作為整個旅游的策劃者和負(fù)責(zé)人,貝茜選擇在湖邊的一家著名的旅館住宿。這個巨大的旅館一共有N (1 <= N <= 50,000)間客房,它們在同一層樓中順次一字排開,在任何一個房間里,只需要拉開窗簾,就能見到波光粼粼的湖面。?
貝茜一行,以及其他慕名而來的旅游者,都是一批批地來到旅館的服務(wù)臺,希望能訂到D_i (1 <= D_i <= N)間連續(xù)的房間。服務(wù)臺的接待工作也很簡單:如果存在r滿足編號為r..r+D_i-1的房間均空著,他就將這一批顧客安排到這些房間入住;如果沒有滿足條件的r,他會道歉說沒有足夠的空房間,請顧客們另找一家賓館。如果有多個滿足條件的r,服務(wù)員會選擇其中最小的一個。?
旅館中的退房服務(wù)也是批量進(jìn)行的。每一個退房請求由2個數(shù)字X_i、D_i描述,表示編號為X_i..X_i+D_i-1 (1 <= X_i <= N-D_i+1)房間中的客人全部離開。退房前,請求退掉的房間中的一些,甚至是所有,可能本來就無人入住。?
而你的工作,就是寫一個程序,幫服務(wù)員為旅客安排房間。你的程序一共需要處理M (1 <= M < 50,000)個按輸入次序到來的住店或退房的請求。第一個請求到來前,旅店中所有房間都是空閑的。
Input
* 第1行: 2個用空格隔開的整數(shù):N、M?
* 第2..M+1行: 第i+1描述了第i個請求,如果它是一個訂房請求,則用2個數(shù)字1、D_i描述,數(shù)字間用空格隔開;如果它是一個退房請求,用3個以空格隔開的數(shù)字2、X_i、D_i描述
Output
* 第1..??行: 對于每個訂房請求,輸出1個獨(dú)占1行的數(shù)字:如果請求能被滿足 ,輸出滿足條件的最小的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
Source
usaco feb2008 金組
仍然用l1,r1,max1分別表示左起最大連續(xù)值,右起最大連續(xù)值和區(qū)間最大連續(xù)值,其中增加sum參數(shù)表示區(qū)間長度
再添加lazy參數(shù),lazy==1表示有人,lazy==2表示沒人,其他細(xì)節(jié)看下面代碼
#include<cstdio> #include<iostream> using namespace std; const int maxn=50005; int n,m,a,b,tot,k; inline void _read(int &x){char t=getchar();bool sign=true;while(t<'0'||t>'9'){if(t=='-')sign=false;t=getchar();}for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';if(!sign)x=-x; } struct wk{int a,b,left,right,sum;int l1,r1,max1,lazy; }tree[2*maxn]; void buildtree(int x,int y){int r=++tot;tree[r].a=x;tree[r].b=y;if(x<y){int mid=(x+y)>>1;tree[r].left=tot+1;buildtree(x,mid);tree[r].right=tot+1;buildtree(mid+1,y);tree[r].l1=tree[r].r1=tree[r].max1=tree[r].sum=y-x+1;}else tree[r].l1=tree[r].r1=tree[r].max1=tree[r].sum=1; } void update(int r){int ls=tree[r].left,rs=tree[r].right;if(tree[ls].sum==tree[ls].max1)tree[r].l1=tree[ls].sum+tree[rs].l1;else tree[r].l1=tree[ls].l1;if(tree[rs].sum==tree[rs].max1)tree[r].r1=tree[rs].sum+tree[ls].r1;else tree[r].r1=tree[rs].r1;tree[r].max1=max(tree[ls].max1,tree[rs].max1);tree[r].max1=max(tree[r].max1,tree[ls].r1+tree[rs].l1); } void putdown(int r){int ls=tree[r].left,rs=tree[r].right;if(tree[r].lazy==1){tree[ls].l1=tree[ls].r1=tree[ls].max1=tree[ls].sum;tree[rs].l1=tree[rs].r1=tree[rs].max1=tree[rs].sum;tree[ls].lazy=tree[rs].lazy=1;}else {tree[ls].l1=tree[ls].r1=tree[ls].max1=0;tree[rs].l1=tree[rs].r1=tree[rs].max1=0;tree[ls].lazy=tree[rs].lazy=2;}tree[r].lazy=0; } void change(int r,int a,int b,int f){if(tree[r].b<a||tree[r].a>b)return;if(tree[r].lazy)putdown(r);if(tree[r].a>=a&&tree[r].b<=b){if(f==1)tree[r].l1=tree[r].r1=tree[r].max1=tree[r].sum;else tree[r].l1=tree[r].r1=tree[r].max1=0;tree[r].lazy=f;return ;}int mid=(tree[r].a+tree[r].b)>>1;if(b<=mid)change(tree[r].left,a,b,f);//交于當(dāng)前討論的區(qū)間的左兒子else if(a>mid)change(tree[r].right,a,b,f);//交于當(dāng)前討論區(qū)間的右兒子else {change(tree[r].left,a,mid,f);change(tree[r].right,mid+1,b,f);}//既交于左兒子,又交于右兒子,就分別遞歸計算update(r); } int ask(int r,int x){int mid=(tree[r].a+tree[r].b)>>1;if(tree[r].lazy)putdown(r);if(tree[r].a==tree[r].b)return tree[r].a;//如果當(dāng)前區(qū)間被壓縮到了一個點(diǎn),就returnif(tree[tree[r].left].max1>=x)return ask(tree[r].left,x);if(tree[tree[r].left].r1+tree[tree[r].right].l1>=x)return mid-tree[tree[r].left].r1+1;return ask(tree[r].right,x); } int main(){_read(n);_read(m);buildtree(1,n);for(int i=1;i<=m;i++){_read(k);if(k==1){_read(b);if(tree[1].max1<b)puts("0");else {int a=ask(1,b);printf("%d\n",a);change(1,a,a+b-1,2);}}else {_read(a);_read(b);change(1,a,a+b-1,1);}} }總結(jié)
以上是生活随笔為你收集整理的NKOI 1550 旅馆的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2011东莞市优秀表彰企业名单
- 下一篇: 区块链+物联网技术结合,区块链技术应用开