不得不说这个题确实是练习线段树的好题,跟Hotel比较类似,但总体来说要难不少。最开始一直想的记录的问题,后来看到别人用vector才发现这样用使代码好写好多~
多的不说了,看代码吧。其实更新那些都还比较常规,主要是vector的运用。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=6e4;
const int maxm=maxn*3;
struct Node
{
int l;
int r;
int len;
int res;
int resl;
int resr;
bool isupdate;
}t[maxm];
struct Operation
{
int begin;
int end;
Operation(){}
Operation(int sbegin,int send)
{
begin=sbegin;
end=send;
}
bool operator < (const Operation &a)const
{
return begin<a.begin;
}
};
int n,m;
vector<Operation> oper;
vector<Operation>::iterator it;
void Build(int l,int r,int index)
{
t[index].l=l;
t[index].r=r;
t[index].len=r-l+1;
t[index].isupdate=false;
t[index].resl=t[index].resr=t[index].res=t[index].len;
if(l==r)
return;
int mid=(l+r)>>1;
Build(l,mid,index<<1);
Build(mid+1,r,index<<1|1);
}
void PushUp(int index)
{
if(t[index<<1].resl==t[index<<1].len)
t[index].resl=t[index<<1].len+t[index<<1|1].resl;
else
t[index].resl=t[index<<1].resl;
if(t[index<<1|1].resr==t[index<<1|1].len)
t[index].resr=t[index<<1|1].len+t[index<<1].resr;
else
t[index].resr=t[index<<1|1].resr;
t[index].res=max(t[index<<1].res,t[index<<1|1].res);
t[index].res=max(t[index].res,max(t[index].resl,t[index].resr));
t[index].res=max(t[index].res,t[index<<1].resr+t[index<<1|1].resl);
}
void PushDown(int index)
{
t[index].isupdate=false;
if(t[index].l==t[index].r)
return;
t[index<<1].isupdate=t[index<<1|1].isupdate=true;
if(t[index].res==t[index].len)
{
t[index<<1].resl=t[index<<1].resr=t[index<<1].res=t[index<<1].len;
t[index<<1|1].resl=t[index<<1|1].resr=t[index<<1|1].res=t[index<<1|1].len;
}
if(!t[index].res)
{
t[index<<1].resl=t[index<<1].resr=t[index<<1].res=0;
t[index<<1|1].resl=t[index<<1|1].resr=t[index<<1|1].res=0;
}
}
void Update(int l,int r,int index,int val)
{
if(t[index].isupdate)
PushDown(index);
if(t[index].l==l&&t[index].r==r)
{
t[index].isupdate=true;
if(!val)
t[index].res=t[index].resl=t[index].resr=t[index].len;
else
t[index].res=t[index].resl=t[index].resr=0;
return;
}
int mid=(t[index].l+t[index].r)>>1;
if(r<=mid)
Update(l,r,index<<1,val);
else if(l>mid)
Update(l,r,index<<1|1,val);
else
{
Update(l,mid,index<<1,val);
Update(mid+1,r,index<<1|1,val);
}
PushUp(index);
}
int Query(int index,int val)
{
if(t[index].res<val)
return -1;
if(t[index].isupdate)
PushDown(index);
if(t[index].l==t[index].r)
return t[index].l;
if(t[index<<1].res>=val)
return Query(index<<1,val);
if(t[index<<1].resr&&t[index<<1].resr+t[index<<1|1].resl>=val)
return t[index<<1].r-t[index<<1].resr+1;
return Query(index<<1|1,val);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
Build(1,n,1);
oper.clear();
while(m--)
{
char op[20];
scanf("%s",op);
if(op[0]=='N')
{
//New
int val;
scanf("%d",&val);
int ans=Query(1,val);
if(ans==-1)
{
printf("Reject New\n");
continue;
}
else
printf("New at %d\n",ans);
Update(ans,ans+val-1,1,1);
Operation opt=Operation(ans,ans+val-1);
it=upper_bound(oper.begin(),oper.end(),opt);
oper.insert(it,opt);
}
else if(op[0]=='F')
{
int val;
scanf("%d",&val);
Operation opt=Operation(val,val);
it=upper_bound(oper.begin(),oper.end(),opt);
int index=it-oper.begin()-1;
if(index==-1||oper[index].end<val)
{
printf("Reject Free\n");
continue;
}
printf("Free from %d to %d\n",oper[index].begin,oper[index].end);
Update(oper[index].begin,oper[index].end,1,0);
oper.erase(oper.begin()+index);
}
else if(op[0]=='G')
{
int val;
scanf("%d",&val);
if(val>oper.size())
printf("Reject Get\n");
else
printf("Get at %d\n",oper[val-1].begin);
}
else
{
//Reset
oper.clear();
Update(1,n,1,0);
printf("Reset Now\n");
}
}
printf("\n");
}
return 0;
}