去年省赛的第八题, “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;
}
浙公网安备 33010602011771号