6 10 New 2 New 5 New 2 New 2 Free 3 Get 1 Get 2 Get 3 Free 3 Reset
New at 1 Reject New New at 3 New at 5 Free from 3 to 4 Get at 1 Get at 5 Reject Get Reject Free Reset Now
题意:
这题和poj3667类似。
见点击打开链接
就是多了一些操作。
对于题目的Reset操作。直接区间更新加个lazy标记就行了。
对于New x直接和hotel的分配房间一样的处理就不说了见我博客。
但是要用一个vector容器来保存分配区间的左右端点。
所以先二分位置按左端点的顺序排。对于二分就用算法模板
upper_bound()函数来实现。
对于Free x操作。先找到x对应的区间。还是二分。如果找到了就区间更新。然后把端点从vector中移除。
对于Get x就简单了。如果x合理就直接输出向量第x个元素的左端点就行了。
#include <iostream> #include<string.h> #include<stdio.h> #include<vector> #include<algorithm> using namespace std; const int maxn=50100; struct node//区间结点 { int l,r; }; vector<node> used; vector<node>::iterator p; int ml[maxn<<2],mr[maxn<<2],ma[maxn<<2]; int st[maxn<<2]; int n,m; bool cmp(node a,node b)//比较函数用于二分查找 { return a.l<b.l; } void btree(int L,int R,int k)//建树 { int ls,rs,mid; ma[k]=ml[k]=mr[k]=R-L+1;//初始化。ma为区间内最大连续房间数。ml为区间左端最大连续房间数。mr为右端。。 st[k]=0;//0表示无标记。1表示区间内房间全被占用。-1表示区间房间全空闲 if(L==R) return; ls=k<<1; rs=k<<1|1; mid=(L+R)>>1; btree(L,mid,ls); btree(mid+1,R,rs); } void change(int L,int R,int k)//根据状态修改结点信息 { if(st[k]==1)//占用 ml[k]=mr[k]=ma[k]=0; else ml[k]=mr[k]=ma[k]=R-L+1; } void pushdown(int L,int R,int k)//下传标记 { int ls,rs,mid; ls=k<<1; rs=k<<1|1; mid=(L+R)>>1; if(st[k]==1)//占用 { st[ls]=st[rs]=1; ml[ls]=mr[ls]=ma[ls]=0; ml[rs]=mr[rs]=ma[rs]=0; } else { st[ls]=st[rs]=-1; ml[ls]=mr[ls]=ma[ls]=mid-L+1; ml[rs]=mr[rs]=ma[rs]=R-mid; } st[k]=0; } void check(int L,int R,int l,int r,int k,int s) { int ls,rs,mid; if(l==L&&r==R) { st[k]=s; change(L,R,k); return; } ls=k<<1; rs=k<<1|1; mid=(L+R)>>1; if(st[k]) pushdown(L,R,k); if(l>mid) check(mid+1,R,l,r,rs,s); else if(r<=mid) check(L,mid,l,r,ls,s); else { check(L,mid,l,mid,ls,s); check(mid+1,R,mid+1,r,rs,s); } ma[k]=max(ma[ls],ma[rs]); ma[k]=max(ma[k],mr[ls]+ml[rs]);//找到最大区间 ml[k]=ml[ls];//最基本的值 mr[k]=mr[rs]; if(ma[ls]==mid-L+1)//若右区间全满 ml[k]+=ml[rs];//可能变成的值 if(ma[rs]==R-mid) mr[k]+=mr[ls]; } int qu(int L,int R,int k,int cost)//传空间大小返回连续区间起始位置 { int ls,rs,mid; if(cost>ma[k]) return 0; if(L==R) return L; ls=k<<1; rs=k<<1|1; mid=(L+R)>>1; if(st[k]) pushdown(L,R,k); if(cost<=ma[ls])//优先取左边编号 return qu(L,mid,ls,cost); else if(cost<=mr[ls]+ml[rs]) return mid-mr[ls]+1; else return qu(mid+1,R,rs,cost); } int main() { int i,st,x; char com[20]; node tt; while(~scanf("%d%d",&n,&m)) { btree(1,n,1); used.clear(); for(i=1; i<=m; i++) { scanf("%s",com); if(com[0]=='R') { check(1,n,1,n,1,-1); used.clear(); printf("Reset Now\n"); continue; } scanf("%d",&x); if(com[0]=='N') { st=qu(1,n,1,x); if(st) { printf("New at %d\n",st); check(1,n,st,st+x-1,1,1); tt.l=st; tt.r=st+x-1; p=upper_bound(used.begin(),used.end(),tt,cmp);//找到第一个大于st的元素位置 used.insert(p,tt); } else printf("Reject New\n"); } else if(com[0]=='F') { tt.l=tt.r=x; p=upper_bound(used.begin(),used.end(),tt,cmp);//找到第一个大于x的位置 st=p-used.begin()-1; if(st==-1||used[st].r<x) printf("Reject Free\n"); else { printf("Free from %d to %d\n",used[st].l,used[st].r); check(1,n,used[st].l,used[st].r,1,-1); used.erase(used.begin()+st); } } else { if(x>used.size()) printf("Reject Get\n"); else printf("Get at %d\n",used[x-1].l); } } printf("\n"); } return 0; }