P2894 [USACO08FEB] Hotel G

[USACO08FEB] Hotel G - 洛谷 

很最近的div3 H 很像

单点变成区间修改了

多一个懒标记就可以了,但是维护范围是1,n,div3 H 是无限值域来找最小位置

找到的条件是seg[1].tmx>=v 否则就是0

// Problem: P2894 [USACO08FEB] Hotel G
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2894
// Memory Limit: 128 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#define INF (1<<30)
using namespace std;
typedef long long ll;
const int N=1e5+9;
struct SEG{
	struct node{
		int l,r,len;
		int tag;
		ll lmx,rmx,tmx;
	}seg[N<<2];
	#define tl(id) id<<1
	#define tr(id) id<<1|1
	#define li inline
	li void pushup(node &id,node &l,node &r){
		id.lmx=l.lmx+r.lmx*(l.lmx==l.len);
		id.rmx=r.rmx+l.rmx*(r.rmx==r.len);
		id.tmx=max(l.tmx,max(r.tmx,l.rmx+r.lmx));
	}
	#define pushup(id) pushup(seg[id],seg[tl(id)],seg[tr(id)])
	li void build(int id,int l,int r){
		seg[id]={l,r,r-l+1,INF};
		if(l==r){
			seg[id]={l,r,r-l+1,INF,1,1,1};
			return;
		}
		int mid=(l+r)>>1;
		build(tl(id),l,mid);
		build(tr(id),mid+1,r);
		pushup(id);
	}
	li int inrange(int L,int R,int l,int r){return L>=l && R<=r;}
	li int outofrange(int L,int R,int l,int r){return L>r || l>R;}
	li void maketag(int id,int l,int r,int v){
		seg[id].tag=v;
		seg[id].lmx=seg[id].rmx=seg[id].tmx=(r-l+1)*(!v);//!v 0->1 ,1->0
	}
	li void pushdown(int id,int l,int r){
		if(seg[id].tag==INF){
			return;
		}
		int mid=(l+r)>>1;
		maketag(tl(id),l,mid,seg[id].tag);
		maketag(tr(id),mid+1,r,seg[id].tag);
		seg[id].tag=INF;
	}
	li void modify(int id,int l,int r,int v){
		if(inrange(seg[id].l,seg[id].r,l,r)){
			maketag(id,seg[id].l,seg[id].r,v);//
		}else if(!outofrange(seg[id].l,seg[id].r,l,r)){
			pushdown(id,seg[id].l,seg[id].r);
			modify(tl(id),l,r,v);
			modify(tr(id),l,r,v);
			pushup(id);
		}
	}
	li ll query(int id,int l,int r,int v){
		if(l==r){
			return l;
		}
		int mid=(l+r)>>1;
		pushdown(id,l,r);
		if(seg[tl(id)].tmx>=v){
			return query(tl(id),l,mid,v);
		}
		if(seg[tl(id)].rmx+seg[tr(id)].lmx>=v){
			return seg[tl(id)].r-seg[tl(id)].rmx+1;
		}
		if(seg[tr(id)].tmx>=v){
			return query(tr(id),mid+1,r,v);
		}
		return 0;
	}
}t;
int main(){
	int n,m;
	cin>>n>>m;
	t.build(1,1,n);
	for(int i=1;i<=m;i++){
		int op;
		cin>>op;
		if(op==1){
			int x;
			cin>>x;
			if(t.seg[1].tmx<x){
				cout<<0<<'\n';
				continue;
			}
			ll tt=t.query(1,1,n,x);
			cout<<tt<<'\n';
			t.modify(1,tt,tt+x-1,1);
		}else{
			int x,y;
			cin>>x>>y;
			t.modify(1,x,x+y-1,0);
		}
	}
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值