链接:http://poj.org/problem?id=3667
题意:一家旅馆,不断有人入住,退房。入住的人要求房号连续,退房是连续房号的房间退掉。
思路:线段树LAZY-TAG+区间合并。相比于最基本的线段树,这道题每个“段”中多了三个标记。
lsum:从最左端开始连续空房。rsum:从最右端开始连续空房。sum:该段中最长连续空房。s是LAZY-TAG,-1表示无操作,0表示清空操作,1表示入住操作。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <cstdlib> #include <cmath> #include <map> #include <set> #include <queue> #include <stack> #include <vector> #include <ctype.h> #include <algorithm> #include <string> #define PI acos(-1.0) #define maxn 50005 #define INF 1<<25 #define MAX 0x7fffffff #define mem(a,b) memset(a,b,sizeof(a)) #define f(i,a,b) for(i=a;i<b;i++) typedef long long ll; using namespace std; struct Line { int l,r; int lsum,rsum,sum; int s; int mid() { return (l+r)>>1; } int len() { return r-l+1; } } line[maxn*4]; int build_tree(int l,int r,int step) { line[step].l=l; line[step].r=r; line[step].lsum=line[step].rsum=line[step].sum=line[step].len(); line[step].s=-1; if(l==r) return 0; build_tree(l,line[step].mid(),step<<1); build_tree(line[step].mid()+1,r,step<<1|1); } int downward(int step) { if(line[step].s!=-1) { line[step<<1].s=line[step<<1|1].s=line[step].s; if(line[step].s==0) { line[step<<1].lsum=line[step<<1].rsum=line[step<<1].sum=line[step<<1].len(); line[step<<1|1].lsum=line[step<<1|1].rsum=line[step<<1|1].sum=line[step<<1|1].len(); } else { line[step<<1].lsum=line[step<<1].rsum=line[step<<1].sum=0; line[step<<1|1].lsum=line[step<<1|1].rsum=line[step<<1|1].sum=0; } line[step].s=-1; } } int upward(int step) { line[step].lsum=line[step<<1].lsum+((line[step<<1].lsum==line[step<<1].len())?line[step<<1|1].lsum:0); line[step].rsum=line[step<<1|1].rsum+(line[step<<1|1].rsum==line[step<<1|1].len()?line[step<<1].rsum:0); line[step].sum=max(line[step<<1].rsum+line[step<<1|1].lsum,max(line[step<<1].sum,line[step<<1|1].sum)); } int query(int t,int step) { if(line[step].l==line[step].r) return 1; downward(step); if(line[step<<1].sum>=t) return query(t,step<<1); else if(line[step<<1].rsum+line[step<<1|1].lsum>=t) return line[step].mid()-line[step<<1].rsum+1; else return query(t,step<<1|1); } int update(int l,int r,int step,int t) { if(l<=line[step].l&&r>=line[step].r) { line[step].s=t; if(t==1) line[step].lsum=line[step].rsum=line[step].sum=0; else line[step].lsum=line[step].rsum=line[step].sum=line[step].len(); return 0; } downward(step); if(line[step].mid()>=r) update(l,r,step<<1,t); else if(line[step].mid()<l) update(l,r,step<<1|1,t); else { update(l,line[step].mid(),step<<1,t); update(line[step].mid()+1,r,step<<1|1,t); } upward(step); } int main() { int tot,tt; scanf("%d%d",&tot,&tt); build_tree(1,tot,1); for(int i=0; i<tt; i++) { int s,L,ls; scanf("%d",&s); if(s==1) { scanf("%d",&L); if(L>line[1].sum) printf("0\n"); else { int ans=query(L,1); printf("%d\n",ans); update(ans,ans+L-1,1,1); } } else { scanf("%d%d",&ls,&L); update(ls,ls+L-1,1,0); } } }
原文:http://blog.csdn.net/ooooooooe/article/details/19779025