POJ 3667 Hotel 线段树(区间合并)

来源:互联网 发布:海贼王霸气败笔知乎 编辑:程序博客网 时间:2024/05/14 17:02

链接: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);        }    }}


0 0