hdu 2871 Memory Control
Memory Control
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3610 Accepted Submission(s): 841
Problem Description
Memory units are numbered from 1 up to N.
A sequence of memory units is called a memory block.
The memory control system we consider now has four kinds of operations:
1. Reset Reset all memory units free.
2. New x Allocate a memory block consisted of x continuous free memory units with the least start number
3. Free x Release the memory block which includes unit x
4. Get x Return the start number of the xth memory block(Note that we count the memory blocks allocated from left to right)
Where 1<=x<=N.You are request to find out the output for M operations.
A sequence of memory units is called a memory block.
The memory control system we consider now has four kinds of operations:
1. Reset Reset all memory units free.
2. New x Allocate a memory block consisted of x continuous free memory units with the least start number
3. Free x Release the memory block which includes unit x
4. Get x Return the start number of the xth memory block(Note that we count the memory blocks allocated from left to right)
Where 1<=x<=N.You are request to find out the output for M operations.
Input
Input contains multiple cases.
Each test case starts with two integer N,M(1<=N,M<=50000) ,indicating that there are N units of memory and M operations.
Follow by M lines,each line contains one operation as describe above.
Each test case starts with two integer N,M(1<=N,M<=50000) ,indicating that there are N units of memory and M operations.
Follow by M lines,each line contains one operation as describe above.
Output
For each “Reset” operation, output “Reset Now”.
For each “New” operation, if it’s possible to allocate a memory block,
output “New at A”,where Ais the least start number,otherwise output “Reject New”.
For each “Free” operation, if it’s possible to find a memory block occupy unit x,
output “Free from A to B”,where A and B refer to the start and end number of the memory block,otherwise output “Reject Free”.
For each “Get” operation, if it’s possible to find the xth memory blocks,
output “Get at A”,where A is its start number,otherwise output “Reject Get”.
Output one blank line after each test case.
For each “New” operation, if it’s possible to allocate a memory block,
output “New at A”,where Ais the least start number,otherwise output “Reject New”.
For each “Free” operation, if it’s possible to find a memory block occupy unit x,
output “Free from A to B”,where A and B refer to the start and end number of the memory block,otherwise output “Reject Free”.
For each “Get” operation, if it’s possible to find the xth memory blocks,
output “Get at A”,where A is its start number,otherwise output “Reject Get”.
Output one blank line after each test case.
Sample Input
6 10
New 2
New 5
New 2
New 2
Free 3
Get 1
Get 2
Get 3
Free 3
Reset
New 2
New 5
New 2
New 2
Free 3
Get 1
Get 2
Get 3
Free 3
Reset
Sample Output
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
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
Source
/* 内存控制 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; }