pku 3667 Hotel

去年省赛的第八题,  “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;

}        

你可能感兴趣的:(pku)