P2894 [USACO08FEB]Hotel G

Rose

用维护区间最长连续1的方法就可以维护

但是还要维护一下最左边,不过这问题不大

维护一个区间最长连续子段,不在意位置就可以了

然后就可以在查询的时候,先看一看在不在左边,在看一看在不在中间,最后看一看在不在右边

就解决了

可见学线段树靠背模板是不行的

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#define lll long long
using namespace std;
int n,m;
int x,y;
struct t{
	int lm;
	int rm;
	int sum;
	int l;
	int lazy;
}tr[500000];
// f=1入住 
void pushdown(int ro){
	if(tr[ro].lazy==1){
		tr[ro<<1].lm=tr[ro<<1].rm=tr[ro<<1].sum=0;
		tr[ro<<1].lazy=1;
		tr[ro<<1|1].lm=tr[ro<<1|1].rm=tr[ro<<1|1].sum=0;
		tr[ro<<1|1].lazy=1;
		tr[ro].lazy=0;
	}
	if(tr[ro].lazy==2){
		tr[ro<<1].lm=tr[ro<<1].rm=tr[ro<<1].sum=tr[ro<<1].l;
		tr[ro<<1].lazy=2;
		tr[ro<<1|1].lm=tr[ro<<1|1].rm=tr[ro<<1|1].sum=tr[ro<<1|1].l;
		tr[ro<<1|1].lazy=2;
		tr[ro].lazy=0;
	}
}
void pushup(int ro){
	tr[ro].sum=max(tr[ro<<1].sum,max(tr[ro<<1|1].sum,tr[ro<<1].rm+tr[ro<<1|1].lm));
	tr[ro].lm=tr[ro<<1].sum==tr[ro<<1].l?tr[ro<<1].sum+tr[ro<<1|1].lm:tr[ro<<1].lm;
	tr[ro].rm=tr[ro<<1|1].sum==tr[ro<<1|1].l?tr[ro<<1|1].sum+tr[ro<<1].rm:tr[ro<<1|1].rm;
}
void add(int ro,int l,int r,int L,int R,int f){
	if(L<=l&&r<=R){
		if(f==1){
			tr[ro].lm=tr[ro].rm=tr[ro].sum=0;
			tr[ro].lazy=1;
		}else{
			tr[ro].lm=tr[ro].rm=tr[ro].sum=tr[ro].l;
			tr[ro].lazy=2;
		}
		return ;
	}
	pushdown(ro);
	int mid=(l+r)>>1;
	if(L<=mid) add(ro<<1,l,mid,L,R,f);
	if(R>mid) add(ro<<1|1,mid+1,r,L,R,f);
	pushup(ro);
}
int que(int ro,int l,int r){
	if(l==r) return l;
	pushdown(ro);
	int mid=(l+r)>>1;
	if(tr[ro<<1].sum>=y){
		return que(ro<<1,l,mid);
	}else
		if(tr[ro<<1].rm+tr[ro<<1|1].lm>=y){
			return mid-tr[ro<<1].rm+1;
		}
	else{
		return que(ro<<1|1,mid+1,r);
	}
}
void ini(int ro,int l,int r){
	if(l==r){
		tr[ro].l=1;
		return ;
	}
	int mid=(l+r)>>1;
	tr[ro].l=(r-l+1);
	ini(ro<<1,l,mid);
	ini(ro<<1|1,mid+1,r);
}
int z;
int main(){
	scanf("%d%d",&n,&m);
	ini(1,1,n);
	add(1,1,n,1,n,2);
	while(m--){
		scanf("%d%d",&x,&y);
		if(x==1){
			if(tr[1].sum>=y){
				int l=que(1,1,n);
				cout<<l<<endl;
				add(1,1,n,l,l+y-1,1);
			}else{
				cout<<0<<endl;
			}
		}else{
			scanf("%d",&z);
			add(1,1,n,y,y+z-1,2);
		}
		
	}
	return 0;
}
	

posted @ 2021-10-05 13:48  Simex  阅读(35)  评论(0编辑  收藏  举报