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