[USACO08FEB]Hotel G
线段树二分,最大字段和
对于操作二,是很简单的区间赋值
对于操作一,长度为\(len\)的,我们要找到最小的的 \(x\) 满足 \([x, x + len -1]\) 的房间为空
在最大字段和的基础上,我们可以求出最长连续空房间的长度,对于要求长度为\(len\)的房间,可以按顺序判断:
- 若左区间的最大长度满足要求,先选择左区间
- \(\text{左区间的右端最大长度} + \text{右区间的左端最大长度} \geq len\), 答案为\(mid - \text{左区间的右端最大长度}\), 此处\(mid\)左区间的右端点
- 若右区间的最大长度满足要求,选择右区间
// AC one more times
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define endl '\n'
#define all(x) (x).begin(), (x).end()
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<long long,long long> PLL;
const int mod = 1e9+7;
const int N=5e5+10;
struct info
{
int s,ls,rs,ms;
};
info operator + (const info &a,const info &b)
{
info t;
t.s=a.s+b.s;
t.ls=a.ls;
t.rs=b.rs;
if(a.ls==a.s)
t.ls=a.s+b.ls;
if(b.rs==b.s)
t.rs=b.s+a.rs;
t.ms=max({a.ms,b.ms,t.ls,t.rs,a.rs+b.ls});
return t;
}
struct segtree
{
struct info val;
int tag,sz;
}seg[N*4];
void update(int id)
{
seg[id].val=seg[id*2].val+seg[id*2+1].val;
}
void settag(int id,int tag)
{
seg[id].tag=tag;
int sz=seg[id].val.s;
if(tag==0)
seg[id].val={sz,0,0,0};
else if(tag==1)
seg[id].val={sz,sz,sz,sz};
}
void pushdown(int id)
{
if(seg[id].tag!=-1)
{
settag(id*2,seg[id].tag);
settag(id*2+1,seg[id].tag);
seg[id].tag=-1;
}
}
void build(int id,int l,int r)
{
seg[id].tag=-1;
seg[id].sz=r-l+1;
if(l==r)
{
seg[id].val={1,1,1,1};
return;
}
int mid=(l+r)>>1;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
update(id);
}
void modify(int id,int l,int r,int ql,int qr,int tag)
{
if(l==ql&&r==qr)
{
settag(id,tag);
return;
}
pushdown(id);
int mid=(l+r)>>1;
if(qr<=mid)
modify(id*2,l,mid,ql,qr,tag);
else if(ql>mid)
modify(id*2+1,mid+1,r,ql,qr,tag);
else
modify(id*2,l,mid,ql,mid,tag),
modify(id*2+1,mid+1,r,mid+1,qr,tag);
update(id);
}
int query(int id,int l,int r,int cnt)
{
if(l==r)
{
return l;
}
pushdown(id);
int mid=(l+r)>>1;
if(seg[id*2].val.ms>=cnt)
return query(id*2,l,mid,cnt);
else if(
seg[id*2].val.rs+seg[id*2+1].val.ls>=cnt)
return mid-seg[id*2].val.rs+1;
else return query(id*2+1,mid+1,r,cnt);
}
void solve()
{
int n,q;
cin>>n>>q;
build(1,1,n);
while(q--)
{
int op; cin>>op;
if(op==1)
{
int x; cin>>x;
if(seg[1].val.ms<x)
{
cout<<0<<endl;
continue;
}
int pos=query(1,1,n,x);
cout<<pos<<endl;
modify(1,1,n,pos,pos+x-1,0);
}
else if(op==2)
{
int x,y; cin>>x>>y;
modify(1,1,n,x,x+y-1,1);
}
}
return;
}
int main()
{
std::ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
int TC = 1;
//cin >> TC;
for(int tc = 1; tc <= TC; tc++)
{
//cout << "Case #" << tc << ": ";
solve();
}
return 0;
}