A-2 LRU-K
分数 25
作者 陈越
单位 浙江大学
Least Recently Used (LRU) cache scheme is to remove the least recently used frame (the one hasn't been used for the longest amount of time) when the cache is full and a new page is referenced which is not there in cache.
LRU-K is a variant of the LRU algorithm, where K represents the number of recent uses. LRU can be considered as LRU-1. Unlike LRU, the LRU-K requires the maintenance of two different queues (for historical access and cache). The data in the historical access queue is not moved to the cache queue until the data is hit K times.
For example, assuming that the length of both queues is 5, and the memory is initialized to be empty. LRU-2 is used to process the data sequence in order: 9,5,6,7,8,3,8,9,5,9,8,3,4,7,5,6. The changes of the historical access queue and the cache queue are shown in the following table:
Data Access | Historical Aaccess Queue | Cache Queue |
---|---|---|
9,5,6,7,8 | 9,5,6,7,8 | Empty |
3 | 5,6,7,8,3 | Empty |
8 | 5,6,7,3 | 8 |
9 | 5,6,7,3,9 | 8 |
5 | 6,7,3,9 | 8,5 |
9 | 6,7,3 | 8,5,9 |
8 | 6,7,3 | 5,9,8 |
3 | 6,7 | 5,9,8,3 |
4 | 6,7,4 | 5,9,8,3 |
7 | 6,4 | 5,9,8,3,7 |
5 | 6,4 | 9,8,3,7,5 |
6 | 4 | 8,3,7,5,6 |
Your job is to implement this LRU-K cache scheme.
Input Specification:
Each input file contains one test case. For each case, the first line gives 3 positive integers: K (≤5), N (≤104) and M (≤105) which are the number of hits for cache, the size of the queues (assuming both queues have the same size) and the number of referenced page ID's. Then M referenced page ID's are given in the next line. A page ID is a number in the range [1,2×104]. All the numbers in a line are separated by a space.
Output Specification:
For each test case, output in the first line the page ID's in the historical access queue, and in the second line, those in the cache queue. The ID's are ordered from front to rear of each queue. All the numbers in a line must be separated by 1 space, and there must be no extra space at the beginning or the end of the line. In case that a queue is empty, output -
in a line instead.文章来源:https://www.toymoban.com/news/detail-478126.html
Sample Input 1:
2 5 17
9 5 6 7 8 3 8 9 5 9 8 3 4 7 5 6 9
Sample Output 1:
4 9
8 3 7 5 6
Sample Input 2:
3 5 10
9 5 6 7 8 3 8 9 5 9
Sample Output 2:
7 3 8 5 9
-
* 解题思路,因为中间涉及值的查找操作,还有删除操作,但是查询以及删除
* 操作都可能在序列中间进行,所以不能用优先队列,优先队列只能在队首
* 进行删除以及查找可以在O(log n)的时间内完成,此时我们就可以想到set
* 或者map,他们在任何位置进行删除以及查找的时间复杂度都是O(lon n);
*
* 由于是LRU算法,所以我们需要两个值来对一个页面进行记录,即页面编号id,
* 最近页面使用的时间代表,时间代表越大,则表示最近刚使用完;因此可以
* 定义一个结构体用set来解决;
*
* 最先使用的优先对列,可是有几个样例过不去(TLE),现在想想也能想明白;文章来源地址https://www.toymoban.com/news/detail-478126.html
/**
* 解题思路,因为中间涉及值的查找操作,还有删除操作,但是查询以及删除
* 操作都可能在序列中间进行,所以不能用优先队列,优先队列只能在队首
* 进行删除以及查找可以在O(log n)的时间内完成,此时我们就可以想到set
* 或者map,他们在任何位置进行删除以及查找的时间复杂度都是O(lon n);
*
* 由于是LRU算法,所以我们需要两个值来对一个页面进行记录,即页面编号id,
* 最近页面使用的时间代表,时间代表越大,则表示最近刚使用完;因此可以
* 定义一个结构体用set来解决;
*
* 最先使用的优先对列,可是有几个样例过不去(TLE),现在想想也能想明白;
*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
struct Infor
{
int id, flag;
bool operator < (const Infor& a) const
{
//先按照flag从小到大,如果flag相等则按照id从小到大排序
//请注意,比较关系一定要写完全,不能只写成flag < a.flag;
//当b.flag == a.flag 时,set就不知道哪个在前,哪个在后,
//或者干脆不知道 a 是否等于 b,因为 a.flag 确实不等于b.flag啊,
//你没有显示的告诉id 和 a.id 的关系
if(flag != a.flag)
return flag < a.flag;
else
return id < a.id;
}
};
const int N = 2e4+10;
set<Infor> cache, hist;
int idx[N]; //最近使用页面的时间代表
int cnt[N]; //页面在history队列中被使用的次数
int k, n, m;
//输出结果
void Print(set<Infor> st)
{
if(st.empty()) puts("-");
else
{
bool spa = false;
for(auto ele : st)
{
if(spa) cout << ' ';
else spa = true;
cout << ele.id;
}
cout << endl;
}
}
int main()
{
cin >> k >> n >> m;
for(int i=0; i<m; ++i)
{
int id;
cin >> id;
//id页面在cache中
if(cache.find({id, idx[id]}) != cache.end())
{
//将id加在cache的末尾
cache.erase({id, idx[id]});
idx[id] = i;
cache.insert({id, idx[id]});
}
else
{
//id在hist中
if(hist.find({id, idx[id]}) != hist.end())
{
++cnt[id];
//id或者加在hist末尾,或者加在cache末尾(当次数达到k)
hist.erase({id, idx[id]});
idx[id] = i;
if(cnt[id] == k)
{
//id加在cache末尾(当次数达到k)
cache.insert({id, idx[id]});
cnt[id] = 0;
if(cache.size() > n)
cache.erase(cache.begin());
//超过容量,去掉“队首”的页面
}
else
//id加在hist末尾
hist.insert({id, idx[id]});
}
else //id不在hist中,id第一次被调入hist中
{
++cnt[id];
idx[id] = i;
hist.insert({id, idx[id]});
} if(hist.size() > n)
{
int id = hist.begin()->id;;
hist.erase(hist.begin());
cnt[id] = 0;
}
}
}
Print(hist);
Print(cache);
return 0;
}
到了这里,关于A-2 LRU-K(攀拓(PAT)- 程序设计(甲级)2023年春季考试仿真卷)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!