目录
- 题目内容
- 解答要求(解答要求限制了只能使用LRU)
- 输入描述
- 样例
- 思路
- 代码
题目内容
你是一名网络工程师,你正在为一家云计算公司开发一个虚拟机管理系统。你的系统需要为每个虚拟机分配一个唯一的ID,用来标识和通信。为了实现这个功能,你设计了一个管理ID的资源池,可以从资源池中分配资源ID和释放资源ID,分配方式有动态分配和指定分配。
动态分配是从资源池的开始分配多个资源ID,这种方式适用于新创建的虚拟机。指定分配是指定一个资源ID进行分配,这种方式适用于恢复或迁移的虚拟机。无论哪种分配方式释放资源ID时都需要放到资源池的尾部,这样可以保证资源ID的重用和均衡。
现在,你已经执行了一系列操作,你需要知道资源池的第一个空闲资源ID应该是多少,以便为下一个虚拟机分配。
注意:
资源池的初始顺序是从小到大。
资源池中空闲资源ID不足时,动态分配失败,对资源池不进行任何操作。指定分配资源ID已经被占用或者不在资源池范围内时,对资源池不进行任何操作。
释放资源ID不在资源池范围内时或者已经是空闲资源ID时,对资源池不进行任何操作。
保证每个用例最后都有空闲资源ID。
解答要求(解答要求限制了只能使用LRU)
时间限制: C/C++ 100ms,其他语言: 200ms
内存限制: C/C++ 32MB,其他语言: 64MB
输入描述
第一行是资源池的范围。
第二行是操作个数。
第三行开始,第一个数字代表操作类型,1表示动态分配,2表示指定分配,3表示释放。
如果第一个数字是1,第二个表示分配的个数;
如果第一个数字是2,第二个表示分配的资源ID;
如果第一个数字是3,第二个表示释放的资源ID.
样例
思路
性能限制很高、数据量很大时,cin、cout肯定是不够快的。
(1)可以利用getchar()速度快的特性设计快读函数读取整数,可以做到用scanf()函数5倍的速度读入任意整数:
#include<cstdio>
// 仅正整数可用
#define read(a) {char c;while((c=getchar())>47) a=a*10+(c^48);}
// 正负整数均可用
inline void read(int& a)
{
register int s = 0, w = 1; //register意思是将变量放入寄存器,大幅提升效率
register char ch = getchar();
while (ch < '0' || ch>'9')
{//为了避免输入数字之前的空格造成影响以及判断正负
if (ch == '-') { w = -1; }
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
s = s * 10 + ch - '0';
ch = getchar();
}
a = s * w;
}
(2)快写,注意<cstdio>
中printf()也比cout快,如果输出不是int类型,可以用printf(“<式样化字符串>”,<参数表>);
输出string:
printf( "%s", s );
输出指定宽度的string:printf(”%.3s“, hello);或者 printf("message: '%.*s'\n", 3, hello);
输出bool类型变量:bool b=true; if(b) printf("true"); else printf("false");
#include<cstdio>
inline void write(int n)
{
if (n < 0)
{
putchar('-');
n *= -1;
}
if (n > 9)
{
write(n / 10);
}
putchar(n % 10 + '0');
}
(3)快速存取:使用满足 LRU (最近最少使用) 缓存 约束的数据结构
思路:使用一个双指针链表和一个哈希表,所有增删查改复杂度为O(1)
双链表表示资源池,存储一个节点被操作(可以是被资源分配,也可以是被释放)的时间戳,且按最近使用时间从左到右排好序,左边的是空闲资源池,右边的是;
哈希表存储key对应的链表中的节点地址(资源id号), 用于key-value 的增删改查;int类型value值表示此时结点是否处于被占用状态。1表示被占用,0表示空闲。
初始化:双链表资源池和哈希表key根据资源池范围初始化,value全部设定为空闲状态0;
操作:分配的本质是从资源池中删除,释放的本质是添加到资源池的末尾
- 动态分配k个资源:
- 用哈希表遍历前k个node对应的value,依次置1;
- 将key对应的节点删除;
- 指定分配第k个资源
- 用哈希表查找key=k的node对应value,将其置1;
- 将key对应的节点删除;
- 释放第k个资源:
- 首先用哈希表判断key对应的结点是否被占用(value是否为1);
- 如果为1,则value置为0表示空闲,同时将key对应的节点放到双链表的最左侧;
1、2需要先判断key对应的value是否为0,然后才能进行操作。
输出:资源池的第一个空闲资源id即链表的第一个结点的key。注意这题保证每个用例最后都有空闲资源ID。
代码
待更新
该题型还包括LC146 LRU缓存,其变种题型为LC469 LFU缓存