[problem description]
There is not much time before the first operating system HNU-OS is released, but some of its components have not been completed, and the memory manager is one of them. According to the developers' plan, in the first version, the memory manager will be very simple and intuitive. It will support three operations:
-
alloc n -- allocate n bytes of memory and return the positive integer identifier X of the allocated block (the initial value of X is 0, and each allocation increases by 1)
-
erase x -- delete the block where identifier x is located
-
Defragment -- defragment the free memory, keep all blocks as close to the beginning of the memory as possible, and maintain their respective order
In this case, the memory model is very simple. It is a sequence of M bytes. For convenience, it is numbered from the first byte to the m-th byte.
The first operation alloc n has a parameter n, which indicates the size of the allocated memory block. When this operation is processed, n consecutive bytes of free blocks will be allocated in memory. If the number of these blocks exceeds one, the block closest to the beginning of memory (i.e. the first byte) is preferred. All these bytes are marked as not free, and the memory manager returns a 32-bit integer digital token representing the identifier of the block. NULL if it is not possible to allocate a free block of this size.
The second operation, erase x, takes x as a parameter to represent the identifier of a block. This action frees up system memory and marks the bytes of this block as free for further use. If this identifier does not point to a previously allocated block that has not yet been released, return ILLEGAL_ERASE_ARGUMENT.
The last operation defragment has no parameters and will only make the occupied memory part closer to the beginning of memory without changing their respective order.
In the current implementation, consecutive integers starting from 1 will be used as identifiers. Each successful alloc operation should return the following number. Unsuccessful alloc operations do not affect the count.
Write the implementation of the memory manager, output the returned value for each alloc command, and output illegal for all failed erase commands_ ERASE_ ARGUMENT.
[input form]
The first row of input data contains two positive integers T and m (1 < = T < = 500, 1 < = m < = 105), where T represents the number of operations that need to be processed by the memory manager, and M represents the effective memory byte size. The next t lines represent an operation.
[output form]
The output has multiple lines. Each line is either the result of the alloc operation or the result of the failed erase operation_ ERASE_ ARGUMENT. The sequence is consistent with the input operation sequence.
[sample input]
6 10
alloc 5
alloc 3
erase 1
alloc 6
defragment
alloc 6
[sample output]
1
2
NULL
3
[example description]
[scoring criteria]
#include<bits/stdc++.h> #define pii pair<int,int> #define fi first #define se second #define mk make_pair using namespace std; int n,m,num=0; int a[100009],b[100009],d[100009]; pii c[509]; bool vis[509]; int main(){ scanf("%d%d",&n,&m); for(int o=1;o<=n;++o){ char C[19];int len,x; scanf("%s",C); if(C[0]=='a'){ scanf("%d",&len); bool bol=0; for(int i=1;i<=m-len+1;++i){ if(a[i]==0&&b[i+len-1]-b[i-1]==0){ // cout<<i<<" "<<i+len-1<<endl; c[++num]=mk(i,i+len-1); for(int j=i;j<=i+len-1;++j)a[j]=1,d[j]=num; printf("%d\n",num); bol=1; break; } } if(!bol)puts("NULL"); } if(C[0]=='e'){ scanf("%d",&x); if(x>num||x<1||vis[x])puts("ILLEGAL_ERASE_ARGUMENT"); else { vis[x]=1; for(int i=c[x].fi;i<=c[x].se;++i)a[i]=0,d[i]=0; } } if(C[0]=='d'){ for(int i=1,la=0;i<=m;++i){ if(!a[i]&&!la)la=i; if(a[i]&&la){ int x=d[i],len=c[x].se-c[x].fi+1; for(int j=c[x].fi;j<=c[x].se;++j)a[j]=d[j]=0; for(int j=la;j<=la+len-1;++j)a[j]=1,d[j]=x; la=0; } } } for(int i=1;i<=m;++i)b[i]=b[i-1]+a[i]; } return 0; } /* 3 10 alloc 10 erase 1 alloc 6 */