Poj 3667 Hotel + Hdu 4553 约会安排 (线段树最左空区间)

题目链接:http://poj.org/problem?id=3667

题意:旅馆的N(1 ≤ n ≤ 50,000) 个房间初始时全为空。现在有M(1 ≤ m < 50,000) 个操作,分为两种:
(1)1  X,要求得到连续的X个房间,输出X个连续房间的最小编号;如果有多个X的连续房间,输出编号最小的一个;不存在输出0;
(2)2  X  Y,将X开始的连续Y个房间退掉。
思路:节点设置本区间最大连续空闲区间,以及从左侧、右侧开始的连续最大空闲空间。更新时注意:
本区间不包含更新区间且本区间满或空时,要将这种状态传递给子区间;
更新返回时用左右子区间的状态更新本区间。

#include <cstdio>
#include <iostream>
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;

struct Node
{
	int left,right,len;
	int maxlen;     //该结点内最长的连续空房间
	int leftlen,rightlen;//该结点内左端点开始的最长连续空房间
						 //右端点结束的最长连续空房间

	void init (int state)
	{
		len=right-left+1;
		maxlen=state*len;
		leftlen=maxlen;
		rightlen=maxlen;
	}
};

Node a[200005];
int n,m;

void Build (int left,int right,int t)
{
	a[t].left=left;
	a[t].right=right;
    a[t].init(1);
	if (a[t].left==a[t].right)
		return;
	int mid=(left+right)>>1;
	Build (left,mid,2*t);
	Build (mid+1,right,2*t+1);
}

int Query (int need,int t)
{
	//如果该结点的最大空长度都不能满足,返回0
	if (a[t].maxlen<need) return 0;

	//如果左侧最大空长度满足,则返回left
	if (a[t].leftlen>=need) return a[t].left; 

	//该节点的左侧不满足,检查左孩子
	//左孩子的最大空长度满足,则答案一定在左孩子中
	if (a[2*t].maxlen>=need) return Query (need,2*t);

	//左孩子右边和右孩子左边加起来满足
	if (a[2*t].rightlen+a[2*t+1].leftlen>=need)
		return a[2*t].right-a[2*t].rightlen+1;

	//以上条件都不满足,检查右孩子是否满足
	return Query (need,2*t+1);
}

void Push_down (int t)
{
	//[left,right]不能完全覆盖该区间,假如该区间以前满或空
	//则将这种状态传给左右孩子
	if (a[t].maxlen==a[t].len || a[t].maxlen==0)
	{
		int st=(a[t].maxlen!=0);
		a[2*t].init(st);
		a[2*t+1].init(st);
	}
}

void Push_up (int t)
{
	a[t].leftlen=a[2*t].leftlen;
	if (a[t].leftlen == a[2*t].right-a[2*t].left+1)
		a[t].leftlen+=a[2*t+1].leftlen;
	a[t].rightlen=a[2*t+1].rightlen;
	if (a[t].rightlen == a[2*t+1].right-a[2*t+1].left+1)
		a[t].rightlen+=a[2*t].rightlen;


	int x=t*2,y=t*2+1;
	a[t].maxlen=max(a[x].maxlen,a[y].maxlen);
	a[t].maxlen=max(a[t].maxlen,max(a[t].leftlen,a[t].rightlen));
	a[t].maxlen=max(a[t].maxlen,a[x].rightlen+a[y].leftlen);

/*第一次写的时候上面三行如下,貌似写得不对,本题可过,Hdu4553过不了
	a[t].maxlen=a[2*t].rightlen+a[2*t+1].leftlen;
	a[t].maxlen=max(a[2*t].maxlen,a[t].maxlen);
	a[t].maxlen=max(a[2*t+1].maxlen,a[t].maxlen);*/
}

//将区间[left,right]的状态更新为state
void Update (int left,int right,int t,int state)
{
	//[left,right]能完全覆盖该区间,更新后返回
	if (a[t].left>=left && a[t].right<=right)
	{
		a[t].init(state);
        return;
	}
	int mid=(a[t].left+a[t].right)>>1;
	Push_down (t);  //更新孩子
	
	if (right<=mid)
		Update (left,right,2*t,state);
	else if (left>mid)
		Update (left,right,2*t+1,state);
	else
	{
		Update (left,mid,2*t,state);
		Update (mid+1,right,2*t+1,state);
	}
	
	Push_up (t);
}

int main ()
{
	scanf("%d%d",&n,&m);
	Build (1,n,1);
	int flag,s,e;
	for (int i=1;i<=m;i++)
	{
		scanf("%d",&flag);
		if (flag==1)
		{
			scanf("%d",&s);
			int temp=Query(s,1);
			printf("%d\n",temp);
			if (temp)
				Update(temp,temp+s-1,1,0);
		}
		else
		{
			scanf("%d%d",&s,&e);
			Update(s,s+e-1,1,1);
		}
	}
	return 0;
}


Hdu 4553

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553

和上面那道题差不多,多记录一组状态。


#include <cstdio>
#include <iostream>
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;

struct Node
{
	int left,right,len;
	int dmlen,nmlen;
	int dl,dr,nl,nr;

	void init_d (int state)
	{
		dmlen=state*len;
		dl=dmlen;
		dr=dmlen;
	}

	void init_n (int state)
	{
		nmlen=state*len;
		nl=nmlen;
		nr=nmlen;
	}
}a[100005*4];

int n,m;

void Build (int left,int right,int t)
{
	a[t].left=left;
	a[t].right=right;
	a[t].len=right-left+1;
    a[t].init_d (1);
	a[t].init_n (1);
	if (a[t].left==a[t].right)
		return;
	int mid=(left+right)>>1;
	Build (left,mid,2*t);
	Build (mid+1,right,2*t+1);
}

int Query_d (int need,int t)
{
	if (a[t].dmlen<need) return 0;
	if (a[t].dl>=need) return a[t].left;
	if (a[2*t].dmlen>=need) return Query_d (need,2*t);
	if (a[2*t].dr+a[2*t+1].dl>=need)
		return a[2*t].right-a[2*t].dr+1;
	return Query_d (need,2*t+1);
}

int Query_n (int need,int t)
{
	if (a[t].nmlen<need) return 0;
	if (a[t].nl>=need) return a[t].left;
	if (a[2*t].nmlen>=need) return Query_n (need,2*t);
	if (a[2*t].nr+a[2*t+1].nl>=need)
		return a[2*t].right-a[2*t].nr+1;
	return Query_n (need,2*t+1);
}

void Push_down (int t)
{
	if (a[t].left==a[t].right)
		return ;

	if (a[t].dmlen==a[t].len || a[t].dmlen==0)
	{
		int st=(a[t].dmlen!=0);
		a[2*t].init_d(st);
		a[2*t+1].init_d(st);
	}
	
	if (a[t].nmlen==a[t].len || a[t].nmlen==0)
	{
		int st=(a[t].nmlen!=0);
		a[2*t].init_n(st);
		a[2*t+1].init_n(st);
	}
}

void Push_up (int t)
{
	if (a[t].left==a[t].right)
		return ;
	a[t].dl=a[2*t].dl;
	if (a[t].dl == a[2*t].right-a[2*t].left+1)
		a[t].dl+=a[2*t+1].dl;
	a[t].dr=a[2*t+1].dr;
	if (a[t].dr == a[2*t+1].right-a[2*t+1].left+1)
		a[t].dr+=a[2*t].dr;

	a[t].dmlen=max(a[2*t].dmlen,a[2*t+1].dmlen);
	a[t].dmlen=max(a[t].dmlen,max(a[t].dl,a[t].dr));
	a[t].dmlen=max(a[t].dmlen,a[2*t].dr+a[2*t+1].dl);
}

void Push_upall (int t)
{
	if (a[t].left==a[t].right)
		return ;
	a[t].dl=a[2*t].dl;
	if (a[t].dl == a[2*t].right-a[2*t].left+1)
		a[t].dl+=a[2*t+1].dl;
	a[t].dr=a[2*t+1].dr;
	if (a[t].dr == a[2*t+1].right-a[2*t+1].left+1)
		a[t].dr+=a[2*t].dr;

	a[t].dmlen=max(a[2*t].dmlen,a[2*t+1].dmlen);
	a[t].dmlen=max(a[t].dmlen,max(a[t].dl,a[t].dr));
	a[t].dmlen=max(a[t].dmlen,a[2*t].dr+a[2*t+1].dl);

	a[t].nl=a[2*t].nl;
	if (a[t].nl == a[2*t].right-a[2*t].left+1)
		a[t].nl+=a[2*t+1].nl;
	a[t].nr=a[2*t+1].nr;
	if (a[t].nr == a[2*t+1].right-a[2*t+1].left+1)
		a[t].nr+=a[2*t].nr;

	a[t].nmlen=max(a[2*t].nmlen,a[2*t+1].nmlen);
	a[t].nmlen=max(a[t].nmlen,max(a[t].nl,a[t].nr));
	a[t].nmlen=max(a[t].nmlen,a[2*t].nr+a[2*t+1].nl);
}

void Updateall (int left,int right,int t,int state)
{
	if (a[t].left>=left && a[t].right<=right)
	{
		a[t].init_d(state);
		a[t].init_n(state);
        return;
	}
	int mid=(a[t].left+a[t].right)>>1;
	Push_down (t);
	
	if (right<=mid)
		Updateall (left,right,2*t,state);
	else if (left>mid)
		Updateall (left,right,2*t+1,state);
	else
	{
		Updateall (left,mid,2*t,state);
		Updateall (mid+1,right,2*t+1,state);
	}
	
	Push_upall (t);
}

void Update (int left,int right,int t,int state)
{
	if (a[t].left>=left && a[t].right<=right)
	{
		a[t].init_d(state);
        return;
	}
	int mid=(a[t].left+a[t].right)>>1;
	Push_down (t);
	
	if (right<=mid)
		Update (left,right,2*t,state);
	else if (left>mid)
		Update (left,right,2*t+1,state);
	else
	{
		Update (left,mid,2*t,state);
		Update (mid+1,right,2*t+1,state);
	}
	
	Push_up (t);
}

int main ()
{
#ifdef ONLINE_JUDGE
#else
	freopen("read.txt","r",stdin);
#endif
	int T;
	scanf("%d",&T);
	for (int Cas=1;Cas<=T;Cas++)
	{
		memset(a,0,sizeof(a));
		printf("Case %d:\n",Cas);
		int at,n;
		scanf("%d%d",&at,&n);
		Build (1,at,1);
		char str[10];
		for (int i=1;i<=n;i++)
		{
			int a,b,t;
			scanf("%s",str);
			if (str[0]=='S')
			{
				scanf("%d%d",&a,&b);
				Updateall(a,b,1,1);
				printf("I am the hope of chinese chengxuyuan!!\n");
			}
			else if (str[0]=='N')
			{
				scanf("%d",&a);
				
				t=Query_d(a,1);
				if (t!=0)
				{
					printf("%d,don't put my gezi\n",t);
					Updateall(t,t+a-1,1,0);
				}
				else
				{
					t=Query_n(a,1);
					if (t!=0)
					{
						printf("%d,don't put my gezi\n",t);
						Updateall(t,t+a-1,1,0);
					}
					else
						printf("wait for me\n");
				}
			}
			else
			{
				scanf("%d",&a);
				t=Query_d(a,1);
				if (t!=0)
				{
					printf("%d,let's fly\n",t);
					Update(t,t+a-1,1,0);
				}
				else
					printf("fly with yourself\n");
			}
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值