6 10 New 2 New 5 New 2 New 2 Free 3 Get 1 Get 2 Get 3 Free 3 Reset
New at 1 Reject New New at 3 New at 5 Free from 3 to 4 Get at 1 Get at 5 Reject Get Reject Free Reset Now
HDU 2871
迄今做的最难的线段树,其实就是HOTEL的加强版,甚至于HOTEL的3个函数都没有任何变化。
内存共四个指令,第一次是New x就是找一段长为X的最左边的区间,这个和HOTEL是没有区别,还是用那三个函数找到最左边的区间并加以更新,ST=1
第二个指令是Free x就是找一个包含X的区间,咋一看以为要重写一个QUERY函数,其实没有必要,使用VECTOR数组保存下每次占领的区间,并且由于VECTOR是向量,可以删除中间的,并任意在中间加区间,十分方便。那我们现在向量里找到那个区间,接着进行更新,ST=0
第三个指令是Get x就是找到第X个区间的范围,用VECTOR的记录很快就能找到
第四个指令Reset,很方面,更新一下即可
另外就是初始化一定要小心
还有就是二分极其容易错,要十分小心
#include<stdio.h>
#include<string.h>
#include<vector>
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
using namespace std;
struct Edge
{
int start,end;
};
vector < Edge > tt;
struct Seg_Tree
{
int l,r,st;
int cval,lval,rval;
void doit() { cval=lval=rval=(st==1? 0 : dis() ); }
int dis() { return (r-l+1); }
int mid() { return (l+r)/2; }
}tree[50010*3];
int n,m;
void build(int left,int right,int idx)
{
tree[idx].l=left;
tree[idx].r=right;
tree[idx].st=-1;
tree[idx].doit();
if(left==right) return ;
int mid=tree[idx].mid();
build(left,mid,LL(idx));
build(mid+1,right,RR(idx));
}
void update(int left,int right,int st,int idx)
{
if(left<=tree[idx].l&&right>=tree[idx].r)
{
tree[idx].st=st;
tree[idx].doit();
return ;
}
if(tree[idx].st!=-1)
{
tree[LL(idx)].st=tree[RR(idx)].st=tree[idx].st;
tree[LL(idx)].doit();
tree[RR(idx)].doit();
tree[idx].st=-1;
}
int mid=tree[idx].mid();
if(mid>=left) update(left,right,st,LL(idx));
if(mid<right) update(left,right,st,RR(idx));
tree[idx].cval=max(tree[LL(idx)].rval+tree[RR(idx)].lval,
max(tree[LL(idx)].cval,tree[RR(idx)].cval));
tree[idx].lval=tree[LL(idx)].lval;
if(tree[LL(idx)].cval==tree[LL(idx)].dis()) tree[idx].lval+=tree[RR(idx)].lval;
tree[idx].rval=tree[RR(idx)].rval;
if(tree[RR(idx)].cval==tree[RR(idx)].dis()) tree[idx].rval+=tree[LL(idx)].rval;
}
int query(int x,int idx)
{
if(tree[idx].l==tree[idx].r)
{
/*if(tree[idx].cval==x)*/ return tree[idx].l;
//else return 0;
}
if(tree[idx].st!=-1)
{
tree[LL(idx)].st=tree[RR(idx)].st=tree[idx].st;
tree[LL(idx)].doit();
tree[RR(idx)].doit();
tree[idx].st=-1;
}
int mid=tree[idx].mid();
if(tree[LL(idx)].cval>=x) return query(x,LL(idx));
else if(tree[LL(idx)].rval+tree[RR(idx)].lval>=x)
return tree[LL(idx)].r-tree[LL(idx)].rval+1;
else if(tree[RR(idx)].cval>=x) return query(x,RR(idx));
else return 0;
}
int half_search(int x)
{
int left=0;
int right=tt.size()-1;
while(left<=right)
{
int mid=(left+right)>>1;
if(tt[mid].start<=x) left=mid+1;
else if(tt[mid].start>x) right=mid-1;
//else break;
}
return left;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(tree,0,sizeof(tree));
tt.clear();
build(1,n,1);
for(int i=1;i<=m;i++)
{
char str[10];
scanf("%s",str);
if(strcmp(str,"Reset")==0)
{
update(1,n,0,1);
tt.clear();
puts("Reset Now");
}
else if(strcmp(str,"New")==0)
{
int x;
scanf("%d",&x);
if(tree[1].cval<x) puts("Reject New");
else
{
Edge buf;
buf.start=query(x,1);
buf.end=buf.start+x-1;
//printf("buf.start=%d end=%d/n",buf.start,buf.end);
int id=half_search(buf.start);
//printf("id=%d/n",id);
tt.insert(tt.begin()+id,buf);
update(buf.start,buf.end,1,1);
printf("New at %d/n",buf.start);
}
}
else if(strcmp(str,"Free")==0)
{
int x;
scanf("%d",&x);
int id=half_search(x)-1;
if(id<=-1||tt[id].end<x) puts("Reject Free");
else
{
update(tt[id].start,tt[id].end,0,1);
printf("Free from %d to %d/n",tt[id].start,tt[id].end);
tt.erase(tt.begin()+id,tt.begin()+id+1);
}
}
else if(strcmp(str,"Get")==0)
{
int x;
scanf("%d",&x);
if(x>tt.size()) puts("Reject Get");
else
{
x--;
printf("Get at %d/n",tt[x].start);
}
}
}
puts("");
}
return 0;
}