Hotel 旅馆
感觉还是比较值得记录了,当时好像只有我和joke用线段树改出来了,其他人都是暴力
//T3 Hotel 旅馆 //我目前有个思路,差分维护树状数组 //这个区间和为零,那说明全是空的 //退房就减去 试试 关键退得时候可能有一些就是零,你还不能直接减 //找空房间也麻烦啊 //woc 找空房间 山海经!!!????? 好家伙 //半小时能写完就写 //我果然写不完,给T1打表去; //这个根据题面,按照我的感觉跟山海经还不一样,山海经重点在 //pushup里,这个重点在延迟标记的下放判断里 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int mx=500000+100; int n,m; struct Node{ int len;//原本长度 int mx;//最大空房间 int lmx;//左端开始最大空 int rmx;//右端开始最大空 int lazy;//住还是清 }t[mx*5]; void Pushup(int k){ if(t[k<<1].len==t[k<<1].mx){ t[k].lmx=t[k<<1].len+t[k<<1|1].lmx; } else t[k].lmx=t[k<<1].lmx; if(t[k<<1|1].len==t[k<<1|1].mx){ t[k].rmx=t[k<<1|1].len+t[k<<1].rmx; } else t[k].rmx=t[k<<1|1].rmx; //左右的sum 和中间 t[k].mx=max(t[k<<1].mx,max(t[k<<1|1].mx,t[k<<1].rmx+t[k<<1|1].lmx)); } void Pushdown(int k){ if(t[k].lazy==-1){ t[k].lazy=0; t[k<<1].lazy=-1; t[k<<1|1].lazy=-1; t[k<<1].mx=t[k<<1].mx=t[k<<1].lmx=t[k<<1].rmx=t[k<<1].len; t[k<<1|1].mx=t[k<<1|1].mx=t[k<<1|1].lmx=t[k<<1|1].rmx=t[k<<1|1].len; } else if(t[k].lazy==1){ t[k].lazy=0; t[k<<1].lazy=1; t[k<<1|1].lazy=1; t[k<<1].mx=t[k<<1].mx=t[k<<1].lmx=t[k<<1].rmx=0; t[k<<1|1].mx=t[k<<1|1].mx=t[k<<1|1].lmx=t[k<<1|1].rmx=0; } } void updata(int l,int r,int L,int R,int k,int flag){ Pushdown(k); // printf("l=%d r=%d L=%d R=%d k=%d flag=%d t[%d].mx=%d\n",l,r,L,R,k,flag,k,t[k].mx); //l L这两组传反了 if(L<=l && R>=r){ if(flag==-1){ t[k].lazy=-1; t[k].mx=t[k].mx=t[k].lmx=t[k].rmx=t[k].len; } else { t[k].lazy=1; t[k].mx=t[k].mx=t[k].lmx=t[k].rmx=0; } } else { int mid=(l+r)/2; if(L<=mid){ updata(l,mid,L,R,k<<1,flag); } if(R>mid){ updata(mid+1,r,L,R,k<<1|1,flag); //这里的k<<1|1写成了k<<1 } Pushup(k); } } int getleft(int d,int l,int r,int k){ Pushdown(k); //printf("l=%d r=%d\n",l,r); if(l==r)return l; int mid=(l+r)/2; if(t[k<<1].mx>=d){ // printf("1k kkkkkkkk\n"); return getleft(d,l,mid,k<<1); } //不用else 我直接return了 if(t[k<<1].rmx+t[k<<1|1].lmx>=d){ // printf("2k kkkkkkkk\n"); return mid-t[k<<1].rmx+1; //如果是在中间,那么左端点直接就出来了,不用管了 } if(t[k<<1|1].mx>=d){ // printf("3k kkkkkkkk\n"); return getleft(d,mid+1,r,k<<1|1); } } void Build(int l,int r,int k){ // printf("kkkkkkkkkkkkk\n"); t[k].lazy=0;//这可千万别忘了,随机值 t[k].len=t[k].mx=t[k].lmx=t[k].rmx=r-l+1; // printf("t[%d].len=%d\n",k,t[k].len); if(l==r)return ; int mid=(l+r)/2; Build(l,mid,k<<1); Build(mid+1,r,k<<1|1); } void Solve(){ scanf("%d%d",&n,&m); Build(1,n,1); for(int i=1;i<=m;++i){ int x; scanf("%d",&x); if(x==1){ int d; scanf("%d",&d); int ans=0; if(t[1].mx<d){ // printf("t[1].mx=%d d=%d\n",t[1].mx,d); ans=0; } else{ ans=getleft(d,1,n,1); // printf("ans=%d\n",ans); updata(1,n,ans,ans+d-1,1,1); } for(int i=1;i<=25;++i){ // printf("t[%d].mx=%d\n",i,t[i].mx); } printf("%d\n",ans); } else { int d1,d2; scanf("%d%d",&d1,&d2); updata(1,n,d1,d2+d1-1,1,-1); //这里也是反了没改 5 5 的意思是5+5-1 你读题啊啊啊 } } } int main(){ freopen("hotel.in","r",stdin); freopen("hotel.out","w",stdout); Solve(); return 0; }
祝您,武运昌隆