Description
Lyf在做操作系统作业的时候,遇到了一题要他实现下Opt算法(全称页面置换最佳淘汰算法)。可是Lyf发现最近好忙啊,于是他想请他的学弟,学妹们帮他来完成。
作业里的内容是这样的:
提出最佳页面淘汰算法。是操作系统存储管理中的一种全局页面替换策略当要调入一页而必须淘汰旧页时,应该淘汰以后不再访问的页,或距现在最长时间后要访问的页面。它所产生的缺页数最少,然而,却需要预测程序的页面引用串,这是无法预知的,不可能对程序的运行过程做出精确的断言。但是我们在这里会告诉你一个已经存在的一个页面序列,请输出最终在内存中存在的页面即可。
Input
有多组数据(组数<=21)。
每组数据输入形如:
n m
a1 a2 a3 a4 …. an
其中n(n,m<=500000)表示已知页面序列的长度。
ai(0<=ai<=100000)表示页面类型,为整数。
m为在内存中保存的页面类型数量。
Output
输出形如:
b1 b2 b3 …. bk
具体要求请仔细阅读样例和Hint。
Sample Input
21 3
7 0 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
3 2
2 1 3
4 3
1 0 0 1
Sample Output
7 0 1
3 1
1 0
题目链接:ZSTU-4272
题目思路:
1.预处理每个数,下一个相同的数最近的位置
2.处理出第一次填满b数组的答案
3.处理替换情况
以下是代码:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <functional>
#include <numeric>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <queue>
#include <deque>
#include <list>
using namespace std;
#define maxn 500005
const int INF = 600000;
int a[maxn];
int b[maxn];//记录答案
int vis[maxn];
int mp[maxn + 50];
int nxt[maxn + 50];
struct node{
int pos,dis,v;
friend bool operator < ( node a, node b ){
if(a.dis!=b.dis) return a.dis<b.dis;
else return a.v<b.v;
}
};
void init()
{
for (int i = 0; i < maxn - 1; i++) b[i] = -1;
memset(vis, 0, sizeof vis);
memset(mp, 0, sizeof mp);
memset(nxt, 0, sizeof nxt);
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m) != EOF)
{
init();
for (int i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
}
//预处理下一个a[i]所在位置
for (int i = n; i >= 1; i--)
{
if (mp[a[i]] == 0)
{
mp[a[i]] = i;
nxt[i] = i;
}
else
{
nxt[i] = mp[a[i]];
mp[a[i]] = i;
}
}
for (int i = 1; i <= n; ++i)
{
if (nxt[i] == i)
{
nxt[i] = INF;
}
}
int pos = 1;
int j = 0;
priority_queue<node> q;
//处理出第一次填满b数组的答案
for (int i = 1; i <= n; i++)
{
if (!vis[a[i]])
{
b[pos] = a[i];
vis[a[i]] = pos;
pos = pos + 1;
}
node tmp;
tmp.pos = vis[a[i]];
tmp.dis = nxt[i];
tmp.v = a[i];
q.push(tmp);
if (pos > m)
{
j = i;
break;
}
}
if (pos <= m) //没填满,直接输出答案
{
if (m > 0) printf("%d",b[1]);
for (int i = 2; i < pos; i++)
{
printf(" %d",b[i]);
}
printf("\n");
continue;
}
//处理替换的情况
for (int i = j + 1; i <= n; i++)
{
if (!vis[a[i]])
{
//取出b数组中,最远出现的位置
node top = q.top();
q.pop();
vis[top.v] = 0;
b[top.pos] = a[i];
vis[a[i]] = top.pos;
}
//不管这个值有没有替换,都将其替换
//之前如果是vis[a[i]],直接continue掉,不对,因为,距离需要更新
node tmp;
tmp.pos = vis[a[i]];
tmp.dis = nxt[i];
tmp.v = a[i];
q.push(tmp);
}
if (m > 0) printf("%d",b[1]);
for (int i = 2; i <= m; i++)
{
printf(" %d",b[i]);
}
printf("\n");
}
return 0;
}