C.Hotel(线段树&最大子段和维护)

题意

​ 区间更新,区间查询最小空区间的左端点。


思路

​ 类似最大子段和的分治维护,线段树维护 3 3 3个变量 l s , r s , s ls,rs,s ls,rs,s左端点最大子段和,右端点最大子段和区间最大子段和。

区间查询时按照左,中,右的顺序满足最优性质。


代码

// Problem: Hotel
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/12156/C
// Memory Limit: 65536 MB
// Time Limit: 2000 ms
// Date: 2021-02-09 20:05:03
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e4+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
#define lx x<<1
#define rx x<<1|1
#define len(x) a[x].r-a[x].l+1
struct node{
	int x,l,r;
	int ls,rs,s,lz;
}a[N<<2];
void re(int x){
	a[x].ls=(a[lx].ls==len(lx))?a[lx].ls+a[rx].ls:a[lx].ls;
	a[x].rs=(a[rx].rs==len(rx))?a[rx].rs+a[lx].rs:a[rx].rs;
	a[x].s=max({a[lx].s,a[rx].s,a[lx].rs+a[rx].ls});
}
void build(int x,int l,int r){
	a[x].l=l,a[x].r=r,a[x].lz=0,a[x].ls=a[x].rs=a[x].s=len(x);
	if(l==r) return;
	int m=l+r>>1;
	build(lx,l,m);
	build(rx,m+1,r);
	re(x);
}
void pushdown(int x){
	if(a[x].lz){
		a[lx].lz=a[rx].lz=a[x].lz;
		a[lx].ls=a[lx].rs=a[lx].s=((a[x].lz==2)?len(lx):0);
		a[rx].ls=a[rx].rs=a[rx].s=((a[x].lz==2)?len(rx):0);
		a[x].lz=0;
	}
}
void update(int x,int l,int r,int op){
	if(a[x].l>=l&&a[x].r<=r){
		a[x].ls=a[x].rs=a[x].s=((op==2)?len(x):0);
		a[x].lz=op;
		return;
	}
	pushdown(x);
	int m=a[x].l+a[x].r>>1;
	if(l<=m) update(lx,l,r,op);
	if(r>m)  update(rx,l,r,op);
	re(x);
}
int query(int x,int v){
	if(a[x].l==a[x].r) return a[x].l;
	pushdown(x);
	int m=a[x].l+a[x].r>>1;
	if(a[lx].s>=v) return query(lx,v);
	if(a[lx].rs+a[rx].ls>=v)  return m-a[lx].rs+1;
	return query(rx,v);
}
int n,m;
int main(){
	scanf("%d%d",&n,&m);
	build(1,1,n);
	while(m--){
		int op,x,d;
		scanf("%d",&op);
		if(op==1){
			scanf("%d",&x);
			if(a[1].s>=x){
				int l=query(1,x);
				update(1,l,l+x-1,1);
				printf("%d\n",l);
			}
			else puts("0");
		}
		else {
			scanf("%d%d",&x,&d);
			update(1,x,x+d-1,2);
		}
	}
	return 0;
}