4272: 最佳淘汰算法
Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 408 Solved: 61
Description
提出最佳页面淘汰算法。是操作系统存储管理中的一种全局页面替换策略当要调入一页而必须淘汰旧页时,应该淘汰以后不再访问的页,或距现在最长时间后要访问的页面。它所产生的缺页数最少,然而,却需要预测程序的页面引用串,这是无法预知的,不可能对程序的运行过程做出精确的断言。但是我们在这里会告诉你一个已经存在的一个页面序列,请输出最终在内存中存在的页面即可。
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 37 0 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 13 22 1 34 31 0 0 1
Sample Output
7 0 13 11 0
HINT
第一个样例:
访问页面7,当前内存中页面数为0,没有达到3页,放入7,当前内存中的页面为(7)
访问页面0,当前内存中页面数为1,没有达到3页,放入0,当前内存中的页面为(7,0)
访问页面0,已经在内存中存在,不做任何操作,当前内存中的页面为(7,0)。
访问页面1,当前内存中页面数为2,没有达到3页,放入1,当前内存中的页面为(7,0,1)。
访问页面2,内存中页数已经达到3页,开始淘汰页面。我们发现在内存中的7下次出现的位置为19, 0为6,1为15,所以7是最长时间后才要访问的,所以7被淘汰。
现在内存中的三个页面变为(2,0,1)。
访问页面0,我们发现0已经存在于我们的内存中,于是我们不做任何如理,继续访问下一个页面。以此类推。
注意如果在某次插入时,在内存中有多种页面在淘汰后不会再被访问,那么我们这次淘汰页面类型号最大的,请看第二个样例。
Source
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <stack>
#include <map>
#include <climits>
using namespace std;
#define LL long long
const int INF=0x3f3f3f3f;
int x[400010],nt[500010],f[500010];
int ans[500010],b[100009];
int n,m,a[500010];
bool visit[100010];
void update(int p,int val,int l,int r,int k)
{
if(l==r)
{
x[k]=val;
return ;
}
int mid=(l+r)/2;
if(p<=mid) update(p,val,l,mid,2*k);
else update(p,val,mid+1,r,2*k+1);
x[k]=max(x[2*k],x[2*k+1]);
}
int get(int l,int r,int k)
{
if(l==r) return l;
int mid=(l+r)/2;
if(x[2*k]>x[2*k+1]) return get(l,mid,2*k);
else return get(mid+1,r,2*k+1);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=0;i<=100000;i++) f[i]=n+1;
for(int i=n;i>=1;i--) nt[i]=f[a[i]],f[a[i]]=i;
memset(visit,0,sizeof visit);
memset(x,0,sizeof x);
memset(ans,0,sizeof ans);
int cnt=0;
for(int i=1;i<=n;i++)
{
if(visit[a[i]])
{
update(a[i],nt[i],0,100000,1);
continue;
}
if(cnt<m)
{
cnt++;
ans[cnt]=a[i];b[a[i]]=cnt;
update(a[i],nt[i],0,100000,1);
}
else
{
int k=get(0,100000,1);
update(k,0,0,100000,1);
int t=b[k];visit[k]=0;
update(a[i],nt[i],0,100000,1);
b[a[i]]=t;ans[t]=a[i];
}
visit[a[i]]=1;
}
for(int i=1;i<=cnt;i++)
{
printf("%d",ans[i]);
if(i<cnt) printf(" ");
else printf("\n");
}
}
return 0;
}