【stl 模拟】 内存分配
传送门
题意
内存的每个地址用一个固定的整数表示,从\(0\)开始排列,程序运行过程中每个进程需要占一定内存
-
对于每个进程有一个申请时间\(t\)
-
需要连续的内存单元数为\(m\)
-
运行时间为\(p\)
-
在运行时间\(p\)内,这\(m\)个内存就不能再被其他进程使用,
在某一时刻\(t\),一个进程申请\(m\)单元的地址,运行时间为\(p\),
-
如果内存中存在长度为\(m\)的地址,则将这个分配
-
存在多个满足的地址时优先分配首地址最小的,如果不存在就加入到等待队列中
-
队列的进程满足时,会优先分配给队列中的,而不是当前时刻新到来的进程
求所有进程运行完毕的时间、等待队列一共被放入的进程个数
数据范围
输入文件数\(\leq 10^{5}\)
\(1\leq t,m,p\leq 10^{9}\)
题解
维护当前的状态:
-
等待队列:(内存长度, 占用时间)
-
内存使用情况:(起始下标,长度)
- 线性扫描、删除、插入:\(set\)
-
小根堆:(释放时间\(key\),起始下标)
新来一个请求:\((T,M,P)\)
-
释放掉所有: 释放时间 \(\leq T\) 的内存,每次释放之后,都要判断等待队列的队头是否可以满足
-
判断\((T,M,P)\)是否可以满足,如果不可以,则插入等待队列
Code
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define fi first
#define se second
#define close ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
const int N=3e4+10;
typedef pair<int,int> pii;
int n;
int t,m,p;
queue<pii>w; //(内存长度,占用时间)
set<pii>mem; //(内存的起始下标,内存的长度)
priority_queue<pii,vector<pii>,greater<pii>>prog; //(释放时间,起始下标)
int cnt,times;
bool push(int t,int m,int p)
{
for(auto it = mem.begin(); it != mem.end(); it++)
{
auto jt = it; // set中的迭代器索引不能用. 用->
jt++; // 当前内存片段的下一个片段,内存片段按照起始下标有序
if(jt != mem.end())
if(m <= jt->fi -(it->fi + it->se -1)-1)
{
int st = it->fi+it->se;
mem.insert({st,m});
prog.push({t+p,st});
return true;
}
}
return false;
}
void finish(int t)
{
while(prog.size() && prog.top().fi <= t)
{
int ed = prog.top().fi;
while(prog.size() && prog.top().fi == ed)
{
auto top=prog.top();
prog.pop();
auto it = mem.lower_bound({top.se,0}); //按照第一关键字进行查找
mem.erase(it);
}
times = ed;
while(w.size())
{
auto h = w.front();
if(push(ed,h.fi,h.se))
w.pop();
else break;
}
}
}
int main()
{
cin>>n;
mem.insert({-1,1});
mem.insert({n,1});
while(cin>>t>>m>>p,t||m||p)
{
finish(t);
if(!push(t,m,p))
{
w.push({m,p});
cnt++;
}
}
finish(2e9);
cout<<times<<endl<<cnt<<endl;
}