题目大意:
Hotel有N(1 ≤ N ≤ 50,000)间rooms,并且所有的rooms都是连续排列在同一边,groups需要check in 房间,要求房间的编号为连续的r..r+Di-1并且r是最小的;visitors同样可能check out,并且他们每次check out都是编号为Xi ..Xi +Di-1 (1 ≤ Xi ≤ N-Di+1)的房间,题目的输入有两种样式:
要求对于每次request,输出为groups分配数目为a的房间中编号最小的房间编号
解题思路:
利用线段树建立模型,维护最大连续区间长度,其中区间长度就是对应的房间数目,并且对应区间中最左边的断点就是answer,同时因为需要求出连续区间的最大长度,因此每次PushUp时都将左右区间合并,lsum维护左区间的最大长度,rsum维护右区间的最大长度,sum维护区间1…N中的最大连续区间长度,lazy标志对应区间是否为空(没有住客)
#include<cstdio> #include<cstring> #include<cmath> #define LL long long #define db double using namespace std; const int maxn = 50000; int lazy[maxn<<2]; int sum[maxn<<2],lsum[maxn<<2],rsum[maxn<<2]; int n,op,a,b,num; int max(int x,int y){ if (x>y) return x; else return y; } int min(int x,int y){ if (x<y) return x; else return y; } void build(int l,int r,int rt){ lazy[rt]=-1; lsum[rt]=rsum[rt]=sum[rt]=r-l+1; if (l==r) return ; int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); } void pushdown(int rt,int k){ if (lazy[rt]!=-1){ lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt]; lsum[rt<<1]=rsum[rt<<1]=sum[rt<<1]=lazy[rt] ? 0:(k-(k>>1)); lsum[rt<<1|1]=rsum[rt<<1|1]=sum[rt<<1|1]=lazy[rt] ? 0:(k>>1); lazy[rt]=-1; } } void pushup(int rt,int k){ lsum[rt]=lsum[rt<<1]; rsum[rt]=rsum[rt<<1|1]; if (lsum[rt]==k-(k>>1)) lsum[rt]+=lsum[rt<<1|1]; if (rsum[rt]==k>>1); rsum[rt]+=rsum[rt<<1]; sum[rt]=max(lsum[rt<<1|1]+rsum[rt<<1],max(sum[rt<<1],sum[rt<<1|1])); } void update(int L,int R,int c,int l,int r,int rt){ if (L<=l && r<=R) { lsum[rt]=rsum[rt]=sum[rt]=c ? 0 : r-l+1; lazy[rt]=c; return ; } pushdown(rt,r-l+1); int mid=(l+r)>>1; if (L<=mid) update(L,R,c,l,mid,rt<<1); if (R>mid) update(L,R,c,mid+1,r,rt<<1|1); pushup(rt,r-l+1); } int query(int w,int l,int r,int rt){ if (l==r) return 1; pushdown(rt,r-l+1); int mid=(l+r)>>1; if (sum[rt<<1]>=w) return query(w,l,mid,rt<<1); else if (rsum[rt<<1]+lsum[rt<<1|1]>=w) return mid-rsum[rt<<1]+1; else return query(w,mid+1,r,rt<<1|1); } int main(){ scanf("%d%d",&n,&num); build(1,n,1); for (int i=1;i<=num;++i){ scanf("%d",&op); if (op==1) { scanf("%d",&a); if (sum[1]<a) printf("0\n"); else { int pos=query(a,1,n,1); printf("%d\n",pos); update(pos,pos+a-1,1,1,n,1); } } else { scanf("%d%d",&a,&b); update(a,a+b-1,0,1,n,1); } } return 0; }