Test instructions
Little Hi and Little ho recently studied the mechanism of memory allocation, and they wrote a relatively simple memory. Memory can be expressed as m contiguous storage space, subscript 0. M-1:
Whenever data is written, the memory-allocation program starts from subscript 0 to the right to find an area sufficient to hold the data and write the data. For example, write a data length of 2, because it is the first data, we use one to represent:
Then continue to write data of length 3 and length 2, then:
When enough data is available, we may encounter enough space left to write down new data. The memory program is then deleted from the earliest data. Let's say we now write the 8th data to fill the memory:
At this point we need to write the 9th data, which has a length of 4. The memory program will erase the 1th data:
But still not enough, so delete the 2nd data. This is enough to put down the 9th data. The memory program then saves a 9th data:
When there is enough space to hold the data, the data is always kept as small as possible on the left (starting point subscript as low as possible).
Little Hi and Little Ho had written the memory and intended to test it. They will write n data consecutively, and after all the data has been written, they want to know what is going on in memory for each storage unit.
Ideas:
A simple idea is that we use an array of length m to simulate the whole memory use scenario.
For 60% of the data: 1≤n≤200,10≤m≤100,1≤k[i]≤5, this simple method is feasible.
For the other 40% of the data, because the maximum length of M can be 10^9, obviously can not be processed, so we need to further optimize.
Through the analysis of simple data, we can find a situation:
an identical number always occupies a contiguous amount of memory .
So we can use it (a,b)
to represent a length b
of a number a
, and we call it a block of data.
For example, memory conditions 1 1 1 1 1 2 2 3 3 0
can be expressed as:
(1,5),(2,2),(3,2),(0,1)
So how do we do the memory operation under the simplified representation method?
Find the leftmost one in memory and (0, b)
meet it at the same time b≥k[i]
.
If b>k[i]
, (0,b)
split into two data blocks(i, k[i]),(0, b-k[i])
If b=k[i]
so, it will be (0,b)
changed directly to(i, b)
Record the location of the first i
data (i, k[i])
to facilitate deletion
According to the record, find i
the block of data (i, k[i])
, and find its previous block (prev, k[prev])
and the next block(next, k[next])
If prev=0
, say, (prev, k[prev])
merge to(i, k[i])
If next=0
, say, (next, k[next])
merge to(i, k[i])
will be (i,k[i])
placed as(0,k[i])
With a simplified representation, memory can have up to 2N blocks, so b≥k[i]
(0, b)
the time complexity is not greater than O (N)even in order to find a satisfied block of data.
The time complexity of the delete operation is O (1), with the data location already recorded.
Depending on the topic, it is possible to add up to N data blocks, so the total time complexity is O (n^2), which solves the problem.
With the algorithm, the next step is to consider how to use the code implementation, here we use the linked list to do:
For each block of data, we represent it in the following way:
Block { key: Represents the data number, a length in the corresponding (a, b) : Indicates the length of the data, corresponding to the B prev in (b) : Represents the previous block of the data block Next: Represents the last block of the block}
Since each block has a front and back pointer, so in order to simplify the processing, we add a two sentinel node to the list, and the initial list state is:
(-10), (0, M), (-10)
Initialize to:
Init (M): Head=NewBlock HeadKey =-1HeadLength =0Head-prev =NULL HeadNext =NULL P=NewBlock PKey =0PLength =M P-prev =Head PNext =NULL HeadNext =p P2=NewBlock P2Key =-1P2Length =0P2-prev =p P2Next =NULL PNext = P
This adds the initial three nodes to the list, followed by a few operations.
Scan directly in order to find compliant(0, b)
Findempty (len): = Head, next , Key! =-1) 0 && P-length >= len) Then // Find the appropriate empty memory segment end If = P-and next end While // no empty memory found
By findEmpty
finding the empty data block and inserting the operation
Insert (Emptyblock, Key, Len)://Emptyblock is an empty block of data found that meets the requirementsIf (Emptyblock-Lenght = =Len) Then EmptyblockKey =key Else P=NewBlock//New (0, b-k[i])P-key =0PLength = Emptyblock-Len P-prev =Emptyblock PNext = EmptyblockNext PNext-prev =P EmptyblockKey =Key EmptyblockLength =Len EmptyblockNext =p End If pos[key]= Emptyblock//record the position of the first key data
pos[key]
to get data blocks by
Delete(Key): P=pos[key] TP= P-Prev//Merge Previous oneIF (TP, key = =0) then PLength = p, length + TP--Length P-prev = TPprev PPrev, next =p Delete TP End If TP= P-Next//after merging aIF (TP, key = =0) then PLength = p, length + TP--Length PNEXT = TP--Next PNext-prev =p Delete tp End If pKey =0
As follows
Main () Input N, M init (m) 0 1 .. N Input K while (true) = findempty (k) ! = NULL) Then Insert (P, I, K) Break Else 1 Delete(lastdeletedata) end If End End for // Type Ans finally outputs the results based on the linked list
The subject in this test is as a medium-sized simple topic design, so time complexity in O (n^2) algorithm can get full marks.
In fact, there is an O (NLOGM) line tree algorithm, which is left for everyone to think about. If you use O (NLOGM) line tree Algorithm AC This problem, welcome to share the thread.
/************************************************author:d evil*********************************************** * */#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#include<queue>#include<Set>#include<map>#include<string>#include<cmath>#include<stdlib.h>#defineINF 0x3f3f3f3f#defineLL Long Long#defineRep (i,a,b) for (int i=a;i<=b;i++)#defineDec (i,a,b) for (int i=a;i>=b;i--)#defineOU (a) printf ("%d\n", a)#definePB Push_back#defineMKP Make_pairTemplate<classT>inlinevoidRD (T &x) {CharC=getchar (); x=0; while(!isdigit (c)) C=getchar (); while(IsDigit (c)) {x=x*Ten+c-'0'; c=GetChar ();}}#defineIn Freopen ("In.txt", "R", stdin);#defineOut Freopen ("OUT.txt", "w", stdout);using namespacestd;Const intmod=1e9+7;Const intn=2e3+Ten;structwq{intId,len; Wq*pre,*NXT;};intN,m,k,ans[n];wq*head,*p,*p2,*tmp,*Pos[n];voidInit () {head=NewWq (); Head->id=-1; Head->len=0; Head->pre=NULL; Head->nxt=NULL; P=NewWq (); P->id=0; P->len=m; P->pre=Head; P->nxt=NULL; Head->nxt=p; P2=NewWq (); P2->id=-1; P2->len=0; P2->pre=p; P2->nxt=NULL; P->nxt=P2;} Wq*findempty (intl) {P=head->NXT; while(p->id!=-1) { if(p->id==0&&P->LEN>=L)returnp; P=p->NXT; } returnNULL;}voidInsert (Wq *now,intIdintl) { if(now->len==l) now->id=ID; Else{p=NewWq (); P->id=0; P->len=now->len-l; P->pre=Now ; P->nxt=now->NXT; P->nxt->pre=p; now->id=ID; now->len=l; now->nxt=p; } Pos[id]=Now ;}voidDelete (intID) {P=Pos[id]; TMP=p->Pre; if(tmp->id==0) {p->len+=tmp->Len; P->pre=tmp->Pre; P->pre->nxt=p; Deletetmp; } tmp=p->NXT; if(tmp->id==0) {p->len+=tmp->Len; P->nxt=tmp->NXT; P->nxt->pre=p; Deletetmp; } P->id=0;}intMain () {RD (n), RD (M); Init (); intlast=0; Rep (I,1, N) {rd (k); while(1) {p=Findempty (k); if(p!=NULL) {Insert (p,i,k); Break; } Else{ Last++; Delete (last); } }} p=head->NXT; intstart=0; memset (ans,-1,sizeof(ans)); while(p->id!=-1) { if(p->id!=0) ans[p->id]=start; Start+=p->Len; P=p->NXT; } Rep (I,0, N)if(ans[i]!=-1) printf ("%d%d\n", I,ans[i]); return 0;}
View Code
hihocoder1198 Memory allocating algorithm (linked list ~)