洛谷 P2894 [USACO08FEB]Hotel G(线段树)
传送门
解题思路
线段树维护区间最长连续0的长度。
板子。
AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int maxn=50005;
int n,m,d[maxn*4],lazy[maxn*4],dl[maxn*4],dr[maxn*4];
void pushdown(int id,int l,int r){
if(~lazy[id]){
int mid=(l+r)/2;
lazy[id*2]=lazy[id];
lazy[id*2+1]=lazy[id];
if(lazy[id]) dl[id*2]=dr[id*2]=d[id*2]=dl[id*2+1]=dr[id*2+1]=d[id*2+1]=0;
else dl[id*2]=dr[id*2]=d[id*2]=mid-l+1,dl[id*2+1]=dr[id*2+1]=d[id*2+1]=r-mid;
lazy[id]=-1;
}
}
void pushup(int id,int l,int r){
int mid=(l+r)/2;
d[id]=max(dr[id*2]+dl[id*2+1],max(d[id*2],d[id*2+1]));
if(dl[id*2]==mid-l+1) dl[id]=dl[id*2]+dl[id*2+1];
else dl[id]=dl[id*2];
if(dr[id*2+1]==r-mid) dr[id]=dr[id*2+1]+dr[id*2];
else dr[id]=dr[id*2+1];
}
void update(int id,int l,int r,int x,int y,int v){
if(x<=l&&r<=y){
if(v) d[id]=dl[id]=dr[id]=0;
else dl[id]=dr[id]=d[id]=r-l+1;
lazy[id]=v;
return;
}
int mid=(l+r)/2;
pushdown(id,l,r);
if(x<=mid) update(id*2,l,mid,x,y,v);
if(y>mid) update(id*2+1,mid+1,r,x,y,v);
pushup(id,l,r);
}
int query(int id,int l,int r,int v){
if(d[id]<v) return -1;
int mid=(l+r)/2;
pushdown(id,l,r);
if(d[id*2]>=v) return query(id*2,l,mid,v);
if(dr[id*2]+dl[id*2+1]>=v) return mid-dr[id*2]+1;
return query(id*2+1,mid+1,r,v);
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ios::sync_with_stdio(false);
memset(lazy,-1,sizeof(lazy));
cin>>n>>m;
update(1,1,n,1,n,0);
for(int i=1;i<=m;i++){
int op;
cin>>op;
if(op==1){
int x;
cin>>x;
int p=query(1,1,n,x);
if(p==-1){
cout<<0<<endl;
continue;
}
cout<<p<<endl;
update(1,1,n,p,p+x-1,1);
}else{
int x,y;
cin>>x>>y;
update(1,1,n,x,x+y-1,0);
}
}
return 0;
}