小HH推荐的题目,说是用Splay-Tree可以过,没想到方法,就先用了线段树,WA了一天啊,没有找出错误,贴代码如下:
#include<iostream> using namespace std; #define MAXN 50002 struct node{ int l,r; int mb,mc; /* 最大空闲区间起始地址和长度 */ int nl,nr; /* 左右起始空闲区间长度 */ char sta; /* 段区间状态 -1:mix */ int bn; /* 段内已用块数量 */ /* 线段两端的块长度,所归属的块 */ int bl,br; /* 两端所归属的块 */ int bln,brn; /* 两端的块长度 */ }tree[MAXN*4]; inline void build(int k,int l,int r){ tree[k].l=l; tree[k].r=r; tree[k].mb=l; tree[k].mc=r-l+1; tree[k].nl=r-l+1; tree[k].nr=r-l+1; tree[k].sta=0; tree[k].bn=0; tree[k].bl=tree[k].br=0; tree[k].bln=tree[k].brn=0; if(l==r) return; else{ int m=(l+r)>>1; build(k*2,l,m); build(k*2+1,m+1,r); } } inline void push_up(int k){ /* update tree[k] nl&nr */ if(tree[k*2].nl==tree[k*2].r-tree[k*2].l+1) tree[k].nl=tree[k*2].nl+tree[k*2+1].nl; else tree[k].nl=tree[k*2].nl; if(tree[k*2+1].nr==tree[k*2+1].r-tree[k*2+1].l+1) tree[k].nr=tree[k*2+1].nr+tree[k*2].nr; else tree[k].nr=tree[k*2+1].nr; /* update tree[k] mb&mc */ if(tree[k*2].mc>=tree[k*2+1].mc){ if(tree[k*2].mc>=tree[k*2].nr+tree[k*2+1].nl){ tree[k].mc=tree[k*2].mc; tree[k].mb=tree[k*2].mb; } else{ tree[k].mc=tree[k*2].nr+tree[k*2+1].nl; tree[k].mb=tree[k*2].r-tree[k*2].nr+1; } } else{ if(tree[k*2+1].mc>=tree[k*2].nr+tree[k*2+1].nl){ tree[k].mc=tree[k*2+1].mc; tree[k].mb=tree[k*2+1].mb; } else{ tree[k].mc=tree[k*2].nr+tree[k*2+1].nl; tree[k].mb=tree[k*2].r-tree[k*2].nr+1; } } /* update tree[k] sta */ if(tree[k*2].sta!=tree[k*2+1].sta) tree[k].sta=-1; else tree[k].sta=tree[k*2].sta; /* update tree[k] bn */ tree[k].bn=tree[k*2].bn+tree[k*2+1].bn; if(tree[k*2].br&&tree[k*2].br==tree[k*2+1].bl) tree[k].bn--; /* update tree[k] bl&br */ tree[k].bl=tree[k*2].bl; tree[k].br=tree[k*2+1].br; /* update tree[k] bln&brn */ if(tree[k*2].br&&tree[k*2].br==tree[k*2+1].bl&&tree[k*2].bln==tree[k*2].r-tree[k*2].l+1) tree[k].bln=tree[k*2].bln+tree[k*2+1].bln; else tree[k].bln=tree[k*2].bln; if(tree[k*2].br&&tree[k*2].br==tree[k*2+1].bl&&tree[k*2+1].brn==tree[k*2+1].r-tree[k*2+1].l+1) tree[k].brn=tree[k*2+1].brn+tree[k*2].brn; else tree[k].brn=tree[k*2+1].brn; return ; } inline void push_down(int k){ /* the segment is blank */ if(tree[k].sta==0){ tree[k*2].mc=tree[k*2].r-tree[k*2].l+1; tree[k*2].mb=tree[k*2].l; tree[k*2].nl=tree[k*2].nr=tree[k*2].mc; tree[k*2].sta=tree[k*2].bn=0; tree[k*2].bl=tree[k*2].br=0; tree[k*2].bln=tree[k*2].brn=0; tree[k*2+1].mc=tree[k*2+1].r-tree[k*2+1].l+1; tree[k*2+1].mb=tree[k*2+1].l; tree[k*2+1].nl=tree[k*2+1].nr=tree[k*2+1].mc; tree[k*2+1].sta=tree[k*2+1].bn=0; tree[k*2+1].bl=tree[k*2+1].br=0; tree[k*2+1].bln=tree[k*2+1].brn=0; } else if(tree[k].sta>=1){ /* the segment is full */ tree[k*2].mc=tree[k*2+1].mc=0; tree[k*2].mb=tree[k*2+1].mb=-1; tree[k*2].nl=tree[k*2+1].nl=0; tree[k*2].nr=tree[k*2+1].nr=0; tree[k*2].sta=tree[k*2+1].sta=tree[k].sta; tree[k*2].bn=tree[k*2+1].bn=1; tree[k*2].bl=tree[k*2+1].bl=tree[k].bl; tree[k*2].br=tree[k*2+1].br=tree[k].br; tree[k*2].bln=tree[k*2].brn=tree[k*2].r-tree[k*2].l+1; tree[k*2+1].bln=tree[k*2+1].brn=tree[k*2+1].r-tree[k*2+1].l+1; } } /* Search the idle block */ inline int search(int k,int d){ if(tree[k].l==tree[k].r) return (tree[k].mc>=d?tree[k].mb:-1); else{ push_down(k); /* 标记下延 */ if(tree[k*2].mc>=d) return search(k*2,d); if(tree[k*2].nr+tree[k*2+1].nl>=d) return tree[k*2].r-tree[k*2].nr+1; if(tree[k*2+1].mc>=d) return search(k*2+1,d); return tree[k].mc>=d?tree[k].mb:-1; } } /* fill(k,l,r): 将[l,r]区间填满 */ inline void fill(int k,int l,int r,int col){ if(l<=tree[k].l&&tree[k].r<=r){ // cout<<tree[k].l<<" "<<tree[k].r<<endl; tree[k].mc=0; tree[k].mb=-1; tree[k].nl=tree[k].nr=0; tree[k].sta=col; tree[k].bn=1; tree[k].bl=tree[k].br=col; tree[k].bln=tree[k].brn=tree[k].r-tree[k].l+1; } else{ push_down(k); int m=(tree[k].l+tree[k].r)>>1; if(l<=m) fill(k*2,l,r,col); if(r>m) fill(k*2+1,l,r,col); push_up(k); } } /* blank(k,l,r): 将[l,r]区间free掉 */ inline void blank(int k,int l,int r){ if(l<=tree[k].l&&r>=tree[k].r){ tree[k].mc=tree[k].r-tree[k].l+1; tree[k].mb=tree[k].l; tree[k].nl=tree[k].mc; tree[k].nr=tree[k].mc; tree[k].sta=0; tree[k].bn=0; tree[k].bl=tree[k].br=0; tree[k].bln=tree[k].brn=0; } else{ push_down(k); int m=(tree[k].l+tree[k].r)>>1; if(l<=m) blank(k*2,l,r); if(r>m) blank(k*2+1,l,r); push_up(k); } } /* myFree(k,x,l,r):将x所在的块[l,r]free掉 */ inline void myFree(int k,int x,int& l,int& r){ if(tree[k].l==tree[k].r){ if(tree[k].sta>0){ l=tree[k].l; r=tree[k].r; return ; } else{ l=r=-1; return ; } } else{ push_down(k); if(tree[k].sta==0){ l=r=-1; return ; } else if(tree[k].sta>=1){ l=tree[k].l; r=tree[k].r; return ; } else{ int m=(tree[k].l+tree[k].r)>>1; if(x<=m){ myFree(k*2,x,l,r); if(r==tree[k*2].r&&tree[k*2].br==tree[k*2+1].bl) r+=tree[k*2+1].bln; return ; } else{ myFree(k*2+1,x,l,r); if(l==tree[k*2+1].l&&tree[k*2+1].bl==tree[k*2].br) l-=tree[k*2].brn; return ; } } } } /* get(k,d):得到第d个block的起始地址 */ inline int get(int k,int d){ if(tree[k].bn<d) return -1; else{ if(tree[k].l==tree[k].r) return tree[k].l; push_down(k); /* 标记下延 */ if(tree[k*2].bn>=d) return get(k*2,d); else{ d-=tree[k*2].bn; if(tree[k*2].br&&tree[k*2].br==tree[k*2+1].bl) d++; return get(k*2+1,d); } } } /******************************Debug***********************/ void Debug(int k){ printf("ID: %2d 区间:[%2d,%2d] State:%2d SegmentNumbers:%2d mc:%2d nl:%2d nr:%2d/n",k,tree[k].l,tree[k].r,tree[k].sta,tree[k].bn,tree[k].mc,tree[k].nl,tree[k].nr); printf(" 左边界 bl=%d bln=%d 右边界br=%d brn=%d/n",tree[k].bl,tree[k].bln,tree[k].br,tree[k].brn); if(tree[k].l==tree[k].r) return ; Debug(k*2); Debug(k*2+1); } /**********************************************************/ int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF){ build(1,1,n); char op[6]; int x; int ret; int col=1; while(m--){ scanf("%s",op); if(op[0]=='N'){ scanf("%d",&x); // Debug(1); ret=search(1,x); // cout<<"New:ret: "<<ret<<endl; if(ret!=-1){ fill(1,ret,ret+x-1,col++); printf("New at %d/n",ret); // Debug(1); } else{ printf("Reject New/n"); } } if(op[0]=='F'){ scanf("%d",&x); int l,r; myFree(1,x,l,r); if(r!=-1){ blank(1,l,r); col--; printf("Free from %d to %d/n",l,r); // Debug(1); } else{ printf("Reject Free/n"); } } if(op[0]=='G'){ scanf("%d",&x); ret=get(1,x); if(ret!=-1){ printf("Get at %d/n",ret); // Debug(1); } else{ printf("Reject Get/n"); } } if(op[0]=='R'){ blank(1,1,n); // Debug(1); col=1; printf("Reset Now/n"); } } printf("/n"); } }
最后利用STL中vector保存memory segment,没想到STL这么强大:
#include<iostream> #include<vector> using namespace std; #define MAXN 50002 struct seg{ int st,et; }; vector<seg> hash; struct node{ int l,r; int mb,mc; /* 最大空闲区间起始地址和长度 */ int nl,nr; /* 左右起始空闲区间长度 */ char sta; /* 段区间状态 -1:mix */ }tree[MAXN*4]; inline void build(int k,int l,int r){ tree[k].l=l; tree[k].r=r; tree[k].mb=l; tree[k].mc=r-l+1; tree[k].nl=r-l+1; tree[k].nr=r-l+1; tree[k].sta=0; if(l==r) return; else{ int m=(l+r)>>1; build(k*2,l,m); build(k*2+1,m+1,r); } } inline void push_up(int k){ /* update tree[k] nl&nr */ if(tree[k*2].nl==tree[k*2].r-tree[k*2].l+1) tree[k].nl=tree[k*2].nl+tree[k*2+1].nl; else tree[k].nl=tree[k*2].nl; if(tree[k*2+1].nr==tree[k*2+1].r-tree[k*2+1].l+1) tree[k].nr=tree[k*2+1].nr+tree[k*2].nr; else tree[k].nr=tree[k*2+1].nr; /* update tree[k] mb&mc */ if(tree[k*2].mc>=tree[k*2+1].mc){ if(tree[k*2].mc>=tree[k*2].nr+tree[k*2+1].nl){ tree[k].mc=tree[k*2].mc; tree[k].mb=tree[k*2].mb; } else{ tree[k].mc=tree[k*2].nr+tree[k*2+1].nl; tree[k].mb=tree[k*2].r-tree[k*2].nr+1; } } else{ if(tree[k*2+1].mc>=tree[k*2].nr+tree[k*2+1].nl){ tree[k].mc=tree[k*2+1].mc; tree[k].mb=tree[k*2+1].mb; } else{ tree[k].mc=tree[k*2].nr+tree[k*2+1].nl; tree[k].mb=tree[k*2].r-tree[k*2].nr+1; } } /* update tree[k] sta */ if(tree[k*2].sta!=tree[k*2+1].sta) tree[k].sta=2; else tree[k].sta=tree[k*2].sta; return ; } inline void push_down(int k){ /* the segment is blank */ if(tree[k].sta==0){ tree[k*2].mc=tree[k*2].r-tree[k*2].l+1; tree[k*2].mb=tree[k*2].l; tree[k*2].nl=tree[k*2].nr=tree[k*2].mc; tree[k*2].sta=0; tree[k*2+1].mc=tree[k*2+1].r-tree[k*2+1].l+1; tree[k*2+1].mb=tree[k*2+1].l; tree[k*2+1].nl=tree[k*2+1].nr=tree[k*2+1].mc; tree[k*2+1].sta=0; } else if(tree[k].sta==1){ /* the segment is full */ tree[k*2].mc=tree[k*2+1].mc=0; tree[k*2].mb=tree[k*2+1].mb=-1; tree[k*2].nl=tree[k*2+1].nl=0; tree[k*2].nr=tree[k*2+1].nr=0; tree[k*2].sta=tree[k*2+1].sta=tree[k].sta; } } /* Search the idle block */ inline int search(int k,int d){ if(tree[k].l==tree[k].r) return (tree[k].mc>=d?tree[k].mb:-1); else{ push_down(k); /* 标记下延 */ if(tree[k*2].mc>=d) return search(k*2,d); if(tree[k*2].nr+tree[k*2+1].nl>=d) return tree[k*2].r-tree[k*2].nr+1; if(tree[k*2+1].mc>=d) return search(k*2+1,d); return tree[k].mc>=d?tree[k].mb:-1; } } /* fill(k,l,r): 将[l,r]区间填满 */ inline void fill(int k,int l,int r){ if(l<=tree[k].l&&tree[k].r<=r){ tree[k].mc=0; tree[k].mb=-1; tree[k].nl=tree[k].nr=0; tree[k].sta=1; } else{ push_down(k); int m=(tree[k].l+tree[k].r)>>1; if(l<=m) fill(k*2,l,r); if(r>m) fill(k*2+1,l,r); push_up(k); } } /* blank(k,l,r): 将[l,r]区间free掉 */ inline void blank(int k,int l,int r){ if(l<=tree[k].l&&r>=tree[k].r){ tree[k].mc=tree[k].r-tree[k].l+1; tree[k].mb=tree[k].l; tree[k].nl=tree[k].mc; tree[k].nr=tree[k].mc; tree[k].sta=0; } else{ push_down(k); int m=(tree[k].l+tree[k].r)>>1; if(l<=m) blank(k*2,l,r); if(r>m) blank(k*2+1,l,r); push_up(k); } } /******************************Debug***********************/ void Debug(int k){ printf("ID: %2d 区间:[%2d,%2d] State:%2d mc:%2d nl:%2d nr:%2d/n",k,tree[k].l,tree[k].r,tree[k].mc,tree[k].nl,tree[k].nr); if(tree[k].l==tree[k].r) return ; Debug(k*2); Debug(k*2+1); } /**********************************************************/ inline int binary_search(int ret){ int low=0,high=hash.size()-1,mid; while(low<=high){ mid=(low+high)>>1; if(ret>=hash[mid].st&&ret<=hash[mid].et) return mid; else if(ret>hash[mid].et) low=mid+1; else high=mid-1; } return low; } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF){ build(1,1,n); char op[6]; int x,y; int ret; hash.clear(); seg tmp; while(m--){ scanf("%s",op); if(op[0]=='N'){ scanf("%d",&x); ret=search(1,x); if(ret!=-1){ fill(1,ret,ret+x-1); tmp.st=ret;tmp.et=ret+x-1; y=binary_search(ret); hash.insert(hash.begin()+y,tmp); printf("New at %d/n",ret); } else{ printf("Reject New/n"); } } if(op[0]=='F'){ scanf("%d",&x); y=binary_search(x); if(y==hash.size()||x<hash[y].st||x>hash[y].et){ printf("Reject Free/n"); } else{ blank(1,hash[y].st,hash[y].et); printf("Free from %d to %d/n",hash[y].st,hash[y].et); hash.erase(hash.begin()+y); } } if(op[0]=='G'){ scanf("%d",&x); x--; if(x>=hash.size()){ printf("Reject Get/n"); } else{ printf("Get at %d/n",hash[x].st); } } if(op[0]=='R'){ blank(1,1,n); hash.clear(); printf("Reset Now/n"); } } printf("/n"); } }