POJ-3667-Hotel

据说比较经典的一道线段树题,大意是说每次操作有订房间和退房间2种,其中要求订房间必须要连续的房间,优先考虑靠左边

思路:根据订房和退房的操作进行标记和删除操作,维护线段树的剩余房间情况和标记情况

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=50010;
struct Tree
{
    int l;
    int r;
    int resl;
    int resr;
    int resm;
    int flag;
}t[maxn*3];
int n,m;
void Build(int l,int r,int index)
{
    t[index].l=l;
    t[index].r=r;
    t[index].resl=t[index].resr=t[index].resm=r-l+1;
    t[index].flag=-1;
    if(l==r)
	return;
    int mid=(l+r)>>1;
    Build(l,mid,index<<1);
    Build(mid+1,r,index<<1|1);
}
void UpdateNode(int index)
{
    if(!t[index].flag)
	t[index].resl=t[index].resr=t[index].resm=t[index].r-t[index].l+1;
    else
	t[index].resl=t[index].resr=t[index].resm=0;
}
void pushdown(int index)
{
    if(t[index].r==t[index].l||t[index].flag==-1)
	return;
    t[index<<1].flag=t[index<<1|1].flag=t[index].flag;
    t[index].flag=-1;
    UpdateNode(index<<1);
    UpdateNode(index<<1|1);
}
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<<1].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;
	UpdateNode(index);
	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 Search(int val,int index)
{
    if(t[index].l==t[index].r)
	return t[index].l;
    pushdown(index);
    if(t[index<<1].resm>=val)
	return Search(val,index<<1);
    if(t[index<<1].resr+t[index<<1|1].resl>=val)
	return t[index<<1].r-t[index<<1].resr+1;
    if(t[index<<1|1].resm>=val)
	return Search(val,index<<1|1);
    return 0;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
	Build(1,n,1);
	while(m--)
	{
	    int op;
	    scanf("%d",&op);
	    if(op==1)
	    {
		int a;
		scanf("%d",&a);
		int ans=Search(a,1);
		printf("%d\n",ans);
		if(ans==0)
		    continue;
		Update(ans,ans+a-1,1,1);
	    }
	    else
	    {
		int a,b;
		scanf("%d%d",&a,&b);
		Update(a,a+b-1,0,1);
	    }
	}

    }
    return 0;
}


你可能感兴趣的:(线段树)