题意:有n个房间排成一排,有m个操作,对于操作1,询问是否有长度为v的连续的空房间,如果有,输出最小的左边的房间的编号,然后旅客将住进这些房间。对于操作2,将x开始,长度为D的房间清空。
思路:线段树。用3个数组tsum,presum,fixsum分别记录当前区间的最长连续空房间的长度、从区间最左边开始最长连续空房间的长度、从区间右边开始最长连续空房间的长度。每次更新时,tsum要么等于左右儿子的tsum的最大值,要么等于左儿子的fixsum的值加上右儿子的presum的值,presum和fixsum更新方法类似。查询时,如果v<tsum[1],则说明没有大于等于v的连续空房子,直接输出0。否则,从左到右查询是否有大于等于v的值。
代码:
#include <iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<cmath> #include<vector> #define inf 0x3f3f3f3f #define Inf 0x3FFFFFFFFFFFFFFFLL #define eps 1e-9 #define pi acos(-1.0) using namespace std; //typedef long long ll; const int maxn=50000+10; int tsum[maxn<<2],presum[maxn<<2],fixsum[maxn<<2],setv[maxn<<2]; void PushUp(int l,int r,int rt) { int ls=rt<<1,rs=rt<<1|1; int m=(l+r)>>1; tsum[rt]=max(tsum[ls],tsum[rs]); tsum[rt]=max(tsum[rt],fixsum[ls]+presum[rs]); presum[rt]=presum[ls]; if(presum[ls]==m-l+1) presum[rt]+=presum[rs]; fixsum[rt]=fixsum[rs]; if(fixsum[rs]==r-m) fixsum[rt]+=fixsum[ls]; } void PushDown(int l,int r,int rt) { if(setv[rt]>=0) { int m=(l+r)>>1; int ls=rt<<1,rs=rt<<1|1; setv[ls]=setv[rs]=setv[rt]; presum[ls]=fixsum[ls]=tsum[ls]=setv[rt]?0:m-l+1; presum[rs]=fixsum[rs]=tsum[rs]=setv[rt]?0:r-m; setv[rt]=-1; } } void build(int l,int r,int rt) { tsum[rt]=presum[rt]=fixsum[rt]=r-l+1; setv[rt]=-1; if(l==r) return; int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); } int Query(int v,int l,int r,int rt) { if(l==r) return l; PushDown(l,r,rt); int m=(l+r)>>1; int ls=rt<<1,rs=rt<<1|1; if(tsum[ls]>=v) return Query(v,l,m,ls); if(presum[rs]+fixsum[ls]>=v) return m-fixsum[ls]+1; return Query(v,m+1,r,rs); } void Update(int v,int L,int R,int l,int r,int rt) { if(l>=L&&r<=R) { setv[rt]=v; presum[rt]=fixsum[rt]=tsum[rt]=v?0:r-l+1; return; } int m=(l+r)>>1; PushDown(l,r,rt); if(m>=L) Update(v,L,R,l,m,rt<<1); if(m<R) Update(v,L,R,m+1,r,rt<<1|1); PushUp(l,r,rt); } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n,m; while(~scanf("%d%d",&n,&m)) { int type,v,x,d; build(1,n,1); while(m--) { scanf("%d",&type); if(type==1) { scanf("%d",&v); if(tsum[1]<v) { printf("0\n"); continue; } int res=Query(v,1,n,1); Update(1,res,res+v-1,1,n,1); printf("%d\n",res); } else { scanf("%d%d",&x,&d); Update(0,x,x+d-1,1,n,1); } } } return 0; }