Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3610 Accepted Submission(s): 841
/* 内存控制 4种操作: 1.Reset 初始化 2.New x 开辟长度为x的连续的空间,输出起始位置 3.Free x 释放包含第x字节的块,整块都释放掉 4.Get x 输出当前状态下,内存里第x块的起始位置 思路: 1.Reset 很简单,update(1,N,EMPTY,1);就可以了 没有必要重新构树 2.New x 对于这个操作,和Hotel这道题是一样的。 建立树的过程中保存了lmax,rmax,max。在查询的 过程中有一些小的技巧。 3.Free x 释放内存,开一个容器,维护这个容器的顺序。 学到了很多容器的知识。海,以前没有学过容器 还是学别人的。 4.Get x 也是通过维护这个容器,来得到的。 详细的见代码 */ #include<cstdio> #include<iostream> #include<cstdlib> #include<algorithm> #include<vector> #define EMPTY 2 //纯色 此题中代表 空的。 #define HH 1 //混色 此题中代表 被占用了。 using namespace std; struct node { int l; int r; int lmax,rmax,max; int len; int color; }f[50003*4]; struct st { int begin; int end; }; vector<st>tom; int hmax(int x,int y) { return x>y? x:y; } bool cmp1(st n1,st n2) { return n1.begin<n2.begin; } void build(int l,int r,int n) //建树。 { int mid=(l+r)/2; f[n].l=l; f[n].r=r; f[n].color=0; f[n].len=f[n].r-f[n].l+1; f[n].lmax=f[n].rmax=f[n].max=f[n].len; if(l==r) return; build(l,mid,n*2); build(mid+1,r,n*2+1); } /* 建设的过程也有一个小小的亮点,可以把 f[n].lmax=f[n].rmax=f[n].max=f[n].len; 用向上更新来写在build(mid+1,r,n*2+1)后,带上 */ void make_down(int n) //向下更新 { if(f[n].color==EMPTY) { f[n*2].max=f[n*2].rmax=f[n*2].lmax=f[n*2].len; f[n*2+1].max=f[n*2+1].rmax=f[n*2+1].lmax=f[n*2+1].len; } else if(f[n].color==HH) { f[n*2].max=f[n*2].lmax=f[n*2].rmax=0; f[n*2+1].max=f[n*2+1].lmax=f[n*2+1].rmax=0; } f[n*2].color=f[n].color; f[n*2+1].color=f[n].color; f[n].color=0; f[n].lmax=f[n].rmax=f[n].max=0; } void make_up(node *father,node *l_child,node *r_child) //向上更新 { father->lmax=(l_child->lmax==l_child->len)? l_child->lmax+r_child->lmax: l_child->lmax; father->rmax=(r_child->rmax==r_child->len)? r_child->rmax+l_child->rmax: r_child->rmax; father->max=hmax(hmax(father->lmax,father->rmax), hmax(l_child->max, hmax(r_child->max,l_child->rmax+r_child->lmax))); } //为什么这道题,有个小小的亮点,没有rnum ,lnum; //仔细一想确实是不需要的.. void update(int l,int r,int num,int n) //更新函数 区间[l,r],更新为num。 { int mid=(f[n].l+f[n].r)/2; if(f[n].l==l && f[n].r==r) { if(num==EMPTY) { f[n].lmax=f[n].rmax=f[n].max=f[n].len; } else f[n].lmax=f[n].rmax=f[n].max=0; f[n].color=num; return; } if(f[n].color!=0) make_down(n); if(mid>=r) update(l,r,num,n*2); else if(mid<l) update(l,r,num,n*2+1); else { update(l,mid,num,n*2); update(mid+1,r,num,n*2+1); } make_up(&f[n],&f[n*2],&f[n*2+1]); } int query(int max,int n) { int cur=0; if(f[n].l==f[n].r) return f[n].l; if(f[n].color!=0) //刚开始,这个别丢了,居然Running time error。 make_down(n); if(f[n*2].max>=max) cur=query(max,n*2); else if(f[n*2].rmax+f[n*2+1].lmax>=max) return f[n*2].r-f[n*2].rmax+1; else if(f[n*2+1].max>=max) cur=query(max,n*2+1); make_up(&f[n],&f[n*2],&f[n*2+1]); return cur; } /* 刚开始 左子树, 然后是 左子树右边最大值+右子树左边最大值 最后才是 右子树 */ void make_ini(int N,int M) { char a[10]; int x,l,r,tmp; st hxl; while(M--) { scanf("%s",a); if(a[0]=='R') { update(1,N,EMPTY,1); tom.clear(); printf("Reset Now\n"); } if(a[0]=='N') { scanf("%d",&x); if(f[1].max<x) { printf("Reject New\n"); } else { l=query(x,1); r=l+x-1; hxl.begin=l; hxl.end=r; vector<st>::iterator it; it=upper_bound(tom.begin(),tom.end(),hxl,cmp1);//二分查找,前提是有序。 tom.insert(it,hxl); printf("New at %d\n",l); update(l,r,HH,1); } } else if(a[0]=='F') { scanf("%d",&x); hxl.begin=x; hxl.end=x; vector<st>::iterator it;//容器的使用啊 it=upper_bound(tom.begin(),tom.end(),hxl,cmp1); tmp=it-tom.begin()-1; if(tmp==-1 || tom[tmp].end<x) printf("Reject Free\n"); else { printf("Free from %d to %d\n",tom[tmp].begin,tom[tmp].end); update(tom[tmp].begin,tom[tmp].end,EMPTY,1); tom.erase(tom.begin()+tmp); } } else if(a[0]=='G') { scanf("%d",&x); if(x>tom.size()) printf("Reject Get\n"); else printf("Get at %d\n",tom[x-1].begin);//容器的下标也是从0开始,所以要减1 } } } int main() { int N,M; while(scanf("%d%d",&N,&M)>0) { tom.clear();//这个必须要的。 build(1,N,1); make_ini(N,M); printf("\n"); //!! } return 0; }