洛谷 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;
}
posted @ 2021-10-12 16:53  尹昱钦  阅读(32)  评论(0编辑  收藏  举报