题目大意
详见题目翻译。
解题思路
L操作也就是区间推平操作,意味着这题可以用珂朵莉树做。
当前块的值为 0 0 0,代表当前区间没有人坐。否则,当前区间有人坐。
A操作就暴力遍历整个集合,寻找一个长度大于 l l l 的块,用 r r r, s u m sum sum 分别表示块的最左边和当前的块长。
如果 s u m ≥ l sum\geq l sum≥l,就直接返回 r r r.
如果当前块的值为 0 0 0, s u m sum sum 加上当前块长,如果 r = 0 r=0 r=0,就将当前块的左边赋值给 r r r.
如果当前块的值为 1 1 1,就将 r r r 和 s u m sum sum 重置为 0 0 0.
L操作就是珂朵莉树基本操作–区间推平。
代码实现
#include<bits/stdc++.h>
using namespace std;
int n,m,ans=0;
char s[10+10];
struct node
{
int l,r;
mutable int v;
node(int L,int R=-1,int V=0)
{
l=L,r=R,v=V;
}
bool operator <(const node &a) const
{
return l<a.l;
}
};
set<node> a;
#define at set<node>::iterator
at split(int pos)
{
at it=a.lower_bound(pos);
if(it!=a.end()&&it->l==pos)
return it;
it--;
int l=it->l;
int r=it->r;
int v=it->v;
a.erase(it);
a.insert(node(l,pos-1,v));
return a.insert(node(pos,r,v)).first;
}
void emerge(int l,int r,int v)
{
at itr=split(r+1);
at itl=split(l);
a.erase(itl,itr);
a.insert(node(l,r,v));
return ;
}
int ask(int l)
{
int r=0,sum=0;
for(at it=a.begin();it!=a.end();++it)
{
if(sum>=l)
return r;
if(it->v==0)
{
if(r==0)
r=it->l;
sum+=it->r-it->l+1;
}
else
r=0,sum=0;
}
return -1;
}
int main()
{
scanf("%d %d",&n,&m);
a.insert(node(1,n,0));
a.insert(node(n+1,n+10,1));
for(int i=1;i<=m;++i)
{
int l,r;
scanf("%s",s);
if(s[0]=='A')
{
scanf("%d",&l);
if(l==5)
l=5;
int r=ask(l);
if(r!=-1)
emerge(r,r+l-1,1);
else
ans++;
}
else
{
scanf("%d %d",&l,&r);
emerge(l,r,0);
}
}
cout<<ans;
return 0;
}