POJ-1823-Hotel

这个题跟3667类似,比3667更简单一些吧,题意仍是宾馆订房退房问题,有3种操作(1、以a号房间开始标记连续订b个房间。2、以a号房间开始连续退b个房间。3、查询当前最长的连续空房间数)

思路:用线段树做,对区间进行标记和删除操作

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=16100;
int n,m;
struct Tree
{
    int l;
    int r;
    int resl;
    int resr;
    int resm;
    int flag;
    void Get()
    {
	resl=resr=resm=flag==0?r-l+1:0;
    }
}t[maxn*3];
void Build(int l,int r,int index)
{
    t[index].l=l;
    t[index].r=r;
    t[index].flag=0;
    t[index].Get();
    if(l==r)
	return;
    int mid=(l+r)>>1;
    Build(l,mid,index<<1);
    Build(mid+1,r,index<<1|1);
}
void pushdown(int index)
{
    if(t[index].l==t[index].r||t[index].flag==-1)
	return;
    t[index<<1].flag=t[index<<1|1].flag=t[index].flag;
    t[index].flag=-1;
    t[index<<1].Get();
    t[index<<1|1].Get();
}
void pushup(int index)
{
    t[index].resm=max(t[index<<1].resr+t[index<<1|1].resl,max(t[index<<1].resm,t[index<<1|1].resm));
    t[index].resl=t[index<<1].resm==t[index<<1].r-t[index].l+1?t[index<<1].resm+t[index<<1|1].resl:t[index<<1].resl;
    t[index].resr=t[index<<1|1].resm==t[index<<1|1].r-t[index<<1|1].l+1?t[index<<1|1].resm+t[index<<1].resr:t[index<<1|1].resr;
}
void Update(int l,int r,int val,int index)
{
    pushdown(index);
    if(t[index].l==l&&t[index].r==r)
    {
	t[index].flag=val;
	t[index].Get();
	return;
    }
    int mid=(t[index].l+t[index].r)>>1;
    if(r<=mid)
	Update(l,r,val,index<<1);
    else if(l>mid)
	Update(l,r,val,index<<1|1);
    else
    {
	Update(l,mid,val,index<<1);
	Update(mid+1,r,val,index<<1|1);
    }
    pushup(index);
}
int main()
{
    scanf("%d%d",&n,&m);
    Build(1,n,1);
    while(m--)
    {
        int op;
        scanf("%d",&op);
        if(op==1)
	{
	    int a,b;
	    scanf("%d%d",&a,&b);
	    Update(a,a+b-1,1,1);
	}
	else if(op==2)
        {
	   int a,b;
	   scanf("%d%d",&a,&b);
	   Update(a,a+b-1,0,1);
	}
	else
	    printf("%d\n",t[1].resm);
    }
    return 0;
}


你可能感兴趣的:(线段树,区间修改)