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
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2871
题意:让你模拟内存控制,可能申请连续x个空间,返回编号最小的位置,或者清空包含x单元的整个空间,返回空间的头和尾,或者获取从左到右数的第x的空间,或者整个内存重置为空。。。。
分析:申请空间和释放空间,和这题很像,只要申请的时候把被覆盖改成被哪个id覆盖,然后开个数组记录这个id的头和尾,释放的时候就可以找到覆盖的id,进而找到头和尾,重置内存其实就是把整个内存都释放掉。。。不用多写函数。。。至于寻找第x个空间,这个比较麻烦,如果另开一棵线段树来统计,我想回好写很多,就单点更新和成段清零,用个延迟标记就行,不过我最后选择直接写在一起了,这个就得有两个延迟标记,一个记录是否要累加,一个记录是否清零,当然,清零的时候累加标记也要清零。。。
一开始少了个清零标记,把清零和累加混在一起了,wa了无数次啊。。。反正写起来实在是麻烦了,或许写成两棵线段树就好很多了,一开始的想法就是两棵线段树的,早上突然想写成一棵 = =,不过别人貌似都是用vector记录。。。。表示很少用那东西- -
2012-10-7:
这题用splay来搞,简直是自虐啊,我调试了整整一个晚上。。。
其实思路就是照搬线段树的那些标记,剩下的就是splay的更新操作边界处理比较麻烦,一般都加上最大和最小两个节点来忽略边界,不过这题这样做似乎导致更多的麻烦T_T
反正我是调到死了。。。400++ms过的,代码巨挫,不想多说了,累了,具体看看代码吧,很容易懂的
代码:
#include<cstdio> #include<iostream> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define uprt rt,m-l+1,r-m using namespace std; const int mm=55555; const int mn=mm<<2; int dly[mn],add[mn],clr[mn],sum[mn],ml[mn],lm[mn],rm[mn]; int sl[mm],sr[mm]; void set(int rt,int id,int len) { ml[rt]=lm[rt]=rm[rt]=id?0:len; if(!id)sum[rt]=add[rt]=0,clr[rt]=1; dly[rt]=id; } void pushdown(int rt,int l1,int l2) { if(dly[rt]>-1) { set(rt<<1,dly[rt],l1); set(rt<<1|1,dly[rt],l2); dly[rt]=-1; } if(clr[rt]) { sum[rt<<1]=sum[rt<<1|1]=add[rt<<1]=add[rt<<1|1]=0; clr[rt<<1]=clr[rt<<1|1]=1; clr[rt]=0; } if(add[rt]) { ++sum[rt<<1],add[rt<<1]=1; add[rt]=0; } } void pushup(int rt,int l1,int l2) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; ml[rt]=max(rm[rt<<1]+lm[rt<<1|1],max(ml[rt<<1],ml[rt<<1|1])); lm[rt]=lm[rt<<1],rm[rt]=rm[rt<<1|1]; if(lm[rt]>=l1)lm[rt]+=lm[rt<<1|1]; if(rm[rt]>=l2)rm[rt]+=rm[rt<<1]; } void build(int l,int r,int rt) { dly[rt]=-1,clr[rt]=add[rt]=sum[rt]=0; ml[rt]=lm[rt]=rm[rt]=r-l+1; if(l==r)return; int m=(l+r)>>1; build(lson); build(rson); } void updata(int L,int R,int id,int l,int r,int rt) { if(L<=l&&R>=r) { set(rt,id,r-l+1); if(id&&L==l)++sum[rt],add[rt]=1; return; } int m=(l+r)>>1; pushdown(uprt); if(L<=m)updata(L,R,id,lson); if(R>m)updata(L,R,id,rson); pushup(uprt); } int NEW(int x,int l,int r,int rt) { if(lm[rt]>=x)return l; int m=(l+r)>>1,ret; pushdown(uprt); if(ml[rt<<1]>=x)ret=NEW(x,lson); else if(rm[rt<<1]+lm[rt<<1|1]>=x)ret=m-rm[rt<<1]+1; else ret=NEW(x,rson); pushup(uprt); return ret; } int FREE(int x,int l,int r,int rt) { if(dly[rt]>-1)return dly[rt]; if(l==r)return 0; int m=(l+r)>>1,ret; pushdown(uprt); if(x<=m)ret=FREE(x,lson); else ret=FREE(x,rson); pushup(uprt); return ret; } int GET(int x,int l,int r,int rt) { if(l==r)return l; int m=(l+r)>>1,ret; pushdown(uprt); if(sum[rt<<1]>=x)ret=GET(x,lson); else ret=GET(x-sum[rt<<1],rson); pushup(uprt); return ret; } int main() { int x,n,m,top; char op[55]; while(~scanf("%d%d",&n,&m)) { build(1,n,1); top=0; while(m--) { scanf("%s",op); if(op[0]=='R') { updata(1,n,0,1,n,1); puts("Reset Now"); } else scanf("%d",&x); if(op[0]=='N') { if(ml[1]>=x) { ++top; sl[top]=NEW(x,1,n,1); sr[top]=sl[top]+x-1; updata(sl[top],sr[top],top,1,n,1); printf("New at %d\n",sl[top]); } else puts("Reject New"); } if(op[0]=='F') { x=FREE(x,1,n,1); if(x) { updata(sl[x],sr[x],0,1,n,1); printf("Free from %d to %d\n",sl[x],sr[x]); } else puts("Reject Free"); } if(op[0]=='G') { if(sum[1]>=x)printf("Get at %d\n",GET(x,1,n,1)); else puts("Reject Get"); } } puts(""); } return 0; }
splay代码:
#include<cstdio> #include<iostream> using namespace std; const int mm=55555; int l[mm],r[mm]; struct SplayTree { int son[mm][2],far[mm],num[mm],val[mm],len[mm],blk[mm],ll[mm],rl[mm],lv[mm],rv[mm],dly[mm]; int rt,size,col; void Link(int x,int y,int c) { far[x]=y,son[y][c]=x; } void Rotate(int x,int c) { int y=far[x]; PushDown(y); PushDown(x); Link(x,far[y],son[far[y]][1]==y); Link(son[x][!c],y,c); Link(y,x,!c); PushUp(y); } void Splay(int x,int g) { for(PushDown(x);far[x]!=g;) { int y=far[x],cx=son[y][1]==x,cy=son[far[y]][1]==y; if(far[y]==g)Rotate(x,cx); else { if(cx==cy)Rotate(y,cy); else Rotate(x,cx); Rotate(x,cy); } } PushUp(x); if(!g)rt=x; } int Select(int k,int g) { int x=rt; PushDown(x); while(num[son[x][0]]!=k) { if(num[son[x][0]]>k)x=son[x][0]; else k-=num[son[x][0]]+1,x=son[x][1]; PushDown(x); } Splay(x,g); return x; } void NewNode(int y,int &x) { x=++size; far[x]=y,num[x]=1,ll[x]=rl[x]=len[x]=1; blk[x]=lv[x]=rv[x]=val[x]=dly[x]=son[x][0]=son[x][1]=0; } void Make(int l,int r,int &x,int y) { if(l>r)return; int m=(l+r)>>1; NewNode(y,x); Make(l,m-1,son[x][0],x); Make(m+1,r,son[x][1],x); PushUp(x); } void Prepare(int n) { NewNode(size=0,rt); NewNode(rt,son[rt][1]); val[1]=val[2]=-1,len[1]=len[2]=0; lv[1]=rv[1]=lv[2]=rv[2]=0; col=ll[1]=rl[1]=ll[2]=rl[2]=0; Make(1,n,son[2][0],2); Splay(2,0); } void Check(int x,int d) { if(!x)return; dly[x]=d; len[x]=ll[x]=rl[x]=(d<0)*num[x]; val[x]=lv[x]=rv[x]=d>0?d:0; blk[x]=d>0; } void PushDown(int x) { if(!dly[x])return; Check(son[x][0],dly[x]); Check(son[x][1],dly[x]); dly[x]=0; } void PushUp(int x) { int a=son[x][0],b=son[x][1]; num[x]=1+num[a]+num[b]; len[x]=max(len[a],len[b]); blk[x]=blk[a]+blk[b]; if(rv[a]&&rv[a]==lv[b])--blk[x]; ll[x]=ll[a],rl[x]=rl[b]; lv[x]=a>2?lv[a]:val[x],rv[x]=b>2?rv[b]:val[x]; if(!val[x]) { len[x]=max(len[x],rl[a]+ll[b]+1); if(len[a]>=num[a])ll[x]+=ll[b]+1; if(len[b]>=num[b])rl[x]+=rl[a]+1; } else if(x>2&&val[x]!=rv[a]&&val[x]!=lv[b])++blk[x]; } void NEW(int a) { if(len[rt]<a) { puts("Reject New"); return; } int x=rt,y,b=a,p=0; PushDown(x); while(x) { if(len[son[x][0]]>=b)x=son[x][0]; else if(rl[son[x][0]]+!val[x]==b)break; else { if(!val[x]&&rl[son[x][0]]+ll[son[x][1]]+1>=b)b-=rl[son[x][0]]+1; p+=num[son[x][0]]+1,x=son[x][1]; } PushDown(x); } p+=num[son[x][0]]-a+1; x=Select(p-1,0); y=Select(p+a,rt); Check(son[y][0],++col); Splay(y,0); l[col]=p,r[col]=p+a-1; printf("New at %d\n",p); } void FREE(int x) { x=Select(x,0); if(val[x]) { int t=val[x]; Select(l[t]-1,0); int y=Select(r[t]+1,rt); Check(son[y][0],-1); Splay(y,0); printf("Free from %d to %d\n",l[t],r[t]); } else puts("Reject Free"); } void GET(int a) { if(a>blk[rt]) { puts("Reject Get"); return; } int x=rt,y; PushDown(x); while(x) { y=son[x][0]; if(blk[y]>=a)x=y; else if(x>2&&val[x]&&val[x]!=rv[y]&&blk[y]+1==a)break; else { a-=blk[y]; if(x>2&&val[x]) { if(val[x]!=rv[y]&&val[x]!=lv[son[x][1]])--a; if(val[x]==rv[y]&&val[x]==lv[son[x][1]])++a; } x=son[x][1]; } PushDown(x); } Splay(x,0); printf("Get at %d\n",l[val[x]]); } void Reset() { Splay(1,0); Splay(2,1); Check(son[2][0],-1); Splay(2,0); puts("Reset Now"); } }spt; int i,n,m; char op[22]; int main() { while(~scanf("%d%d",&n,&m)) { spt.Prepare(n); while(m--) { scanf("%s",op); if(op[0]!='R')scanf("%d",&i); if(op[0]=='N')spt.NEW(i); if(op[0]=='F')spt.FREE(i); if(op[0]=='G')spt.GET(i); if(op[0]=='R')spt.Reset(); } puts(""); } return 0; }