去年省赛的第八题,  “ROOM ASSIGNATION”。

和我前几天写的  求某个区间中出现最多的数  差不多。。

都是要记录左右端点的连续情况。。

题目的意思很简单,问你有没有连续的n的房间,如果有,就输出以那个房间开始(最小的)。

如果没有就输出0;

还有一种情况:客人要退房间,然后退掉n——n+len-1 这些房间。

具体的看代码(其中的updata1,updata2,基本上一样,完全可以只用其中的一个函数,为了方便起见,我没有融合,一个是释放的房间,一个是占用房间)

# include<stdio.h>
# include<string.h>
# define N 50005
struct node{
	int l,r;
	int count,num;//记录该节点中连续房间数目的最大值,num记录是从哪一个房间开始的
	int cp;//标记节点是否被完全的占用,或完全的没有被占用
	int lcount,rcount;///存左,右端连续的房间的个数
}tree[4*N];
int MM;
void bulid(int l,int r,int t)
{
	int mid;
	tree[t].cp=0;
	tree[t].l=l;
	tree[t].r=r;
	tree[t].count=tree[t].lcount=tree[t].rcount=r-l+1;
	tree[t].num=l;
	if(l==r) return;
	mid=(l+r)/2;
	bulid(l,mid,2*t);
	bulid(mid+1,r,2*t+1);
}
void query(int len,int t)
{
	if(tree[t].l == tree[t].r) {MM=tree[t].l;return;}
	if(tree[2*t].count>=len) query(len,2*t);
	else if(tree[2*t].rcount+tree[2*t+1].lcount>=len)
	{
		MM=tree[2*t].r-tree[2*t].rcount+1;
	}
	else if(tree[2*t+1].count>=len) 
	{
		query(len,2*t+1);
	}
	else 
	{
		MM=tree[t].num;
	}
}
void updata1(int l,int r,int t)
{
	int ans1,ans;
	if(tree[t].l==l && tree[t].r==r)
	{
		tree[t].count=tree[t].lcount=tree[t].rcount=r-l+1;
		tree[t].num=l;
		tree[t].cp=1;
		return;
	}
	if(tree[t].cp!=0) //父亲节点影响子节点
	{
		tree[2*t].cp=tree[2*t+1].cp=tree[t].cp;
		if(tree[t].cp==1)
		{
			tree[2*t].count=tree[2*t].lcount=tree[2*t].rcount=tree[2*t].r-tree[2*t].l+1;
			tree[2*t].num=tree[2*t].l;
			tree[2*t+1].count=tree[2*t+1].lcount=tree[2*t+1].rcount=tree[2*t+1].r-tree[2*t+1].l+1;
			tree[2*t+1].num=tree[2*t+1].l;
		}
		else 
		{
			tree[2*t].count=tree[2*t].lcount=tree[2*t].rcount=0;
			tree[2*t+1].count=tree[2*t+1].lcount=tree[2*t+1].rcount=0;
		}
		tree[t].cp=0;
	}
	if(r<=tree[2*t].r) updata1(l,r,2*t);
	else if(l>=tree[2*t+1].l) updata1(l,r,2*t+1);
	else
	{
		updata1(l,tree[2*t].r,2*t);
		updata1(tree[2*t+1].l,r,2*t+1);
	}
	if(tree[2*t].count>=tree[2*t+1].count)
	{
		tree[t].count=tree[2*t].count;
		tree[t].num=tree[2*t].num;
	}
	else 
	{
		tree[t].count=tree[2*t+1].count;
		tree[t].num=tree[2*t+1].num;
	}
	tree[t].lcount=tree[2*t].lcount;
	tree[t].rcount=tree[2*t+1].rcount;
	if(tree[2*t].rcount!=0 && tree[2*t+1].lcount!=0)
	{
		ans=tree[2*t].rcount+tree[2*t+1].lcount;
		if(ans>tree[t].count) //判断会不会左右子树合并之后出现最大值。
		{
			tree[t].count=ans;
			tree[t].num=tree[2*t].r-tree[2*t].rcount+1;
		}
		else if(ans==tree[t].count)//如果连续的房间数目相等,找到房间标号最小的
		{
			ans1=tree[2*t].r-tree[2*t].rcount+1;
			if(ans1<tree[t].num) tree[t].num=ans1;
		}
		if(tree[2*t].count==tree[2*t].r-tree[2*t].l+1)//如果左子树整个都没被占用的,那该节点的lcount值要加上右子树的rcount值
		{
			tree[t].lcount+=tree[2*t+1].lcount;
		}
		if(tree[2*t+1].count==tree[2*t+1].r-tree[2*t+1].l+1)
		{//如果右子树整个都没被占用的,那该节点的rcount值要加上左子树的lcount值
			tree[t].rcount+=tree[2*t].rcount;
		}
	}
}
void updata2(int l,int r,int t)
{
	int ans,ans1;
	if(tree[t].l==l && tree[t].r==r) 
	{
		tree[t].count=tree[t].lcount=tree[t].rcount=0;
		tree[t].cp=-1;
		return ;
	}
	if(tree[t].cp!=0) 
	{
		tree[2*t].cp=tree[2*t+1].cp=tree[t].cp;
		if(tree[t].cp==1)
		{
			tree[2*t].count=tree[2*t].lcount=tree[2*t].rcount=tree[2*t].r-tree[2*t].l+1;
			tree[2*t].num=tree[2*t].l;
			tree[2*t+1].count=tree[2*t+1].lcount=tree[2*t+1].rcount=tree[2*t+1].r-tree[2*t+1].l+1;
			tree[2*t+1].num=tree[2*t+1].l;
		}
		else 
		{
			tree[2*t].count=tree[2*t].lcount=tree[2*t].rcount=0;
			tree[2*t+1].count=tree[2*t+1].lcount=tree[2*t+1].rcount=0;
		}
		tree[t].cp=0;
	}
	if(r<=tree[2*t].r) updata2(l,r,2*t);
	else if(l>=tree[2*t+1].l) updata2(l,r,2*t+1);
	else
	{
		updata2(l,tree[2*t].r,2*t);
		updata2(tree[2*t+1].l,r,2*t+1);
	}
	if(tree[2*t].count >= tree[2*t+1].count) 
	{
		tree[t].count=tree[2*t].count;
		tree[t].num=tree[2*t].num;
	}
	else 
	{
		tree[t].count=tree[2*t+1].count;
		tree[t].num=tree[2*t+1].num;
	}
	tree[t].lcount=tree[2*t].lcount;
	tree[t].rcount=tree[2*t+1].rcount;
	if(tree[2*t].rcount!=0 && tree[2*t+1].lcount!=0)
	{
		ans=tree[2*t].rcount+tree[2*t+1].lcount;
		if(ans>tree[t].count)
		{
			tree[t].count=ans;
			tree[t].num=tree[2*t].r-tree[2*t].rcount+1;
		}
		else if(ans==tree[t].count)
		{
			ans1=tree[2*t].r - tree[2*t].rcount+1;
			if(ans1<tree[t].num) ans1=tree[t].num;
		}
		if(tree[2*t].count==tree[2*t].r-tree[2*t].l+1)
			tree[t].lcount+=tree[2*t+1].lcount;
		if(tree[2*t+1].count==tree[2*t+1].r- tree[2*t+1].l+1)
			tree[t].rcount+=tree[2*t].rcount;
	}
}
int main()
{
	int n,q,len,z,start;
	while(scanf("%d%d",&n,&q)!=EOF)
	{
		bulid(1,n,1);
		while(q--)
		{
			scanf("%d",&z);
			if(z==2) 
			{
				scanf("%d%d",&start,&len);
				updata1(start,start+len-1,1);
			}
			else 
			{
				scanf("%d",&len);
				if(tree[1].count<len)
					printf("0\n");
				else
				{
					query(len,1);
					printf("%d\n",MM);
					updata2(MM,MM+len-1,1);
				}
			}
		}
	}
	return 0;
}        
posted on 2011-05-13 16:09  奋斗青春  阅读(271)  评论(0编辑  收藏  举报