【BZOJ1206】【HNOI2005】虚拟内存,我也就能写写这种模拟题了

Time Limit: 50 Sec Memory Limit: 162 MB
Submit: 313 Solved: 197

Description

操作系统中一种重要的存储管理技术就是虚拟内存技术。操作系统中允许进程同时运行,也就是并行。每个进程都有其相对独立的数据块(进程运行的过程中将对其进行读写操作)。理想的情况下,这些数据块都应该存放在内存中,这样才能实现高效的读写操作。但事实上,内存的容量有限,每个进程只能把一部分数据放在内存中,为了解决这个矛盾,提出了虚拟内存技术。虚拟内存技术的基本原理是:对进程而言,内存空间是无限大的,进程可以随意地读写数据,而对操作系统内部而言,利用外存来模拟扩充的内存空间,进程要求访问某个内存单元时,交由操作系统处理,操作系统首先在内存中查找该单元是否存在,如果存在,查找成功,否则转入外存查找(一定存在于外存中)。就存储介质的物理性质而言,内存的访问速度相对于外存要快得多,因此对于每个进程来说操作系统应该把那些访问次数较多的数据存放在内存中,而把那些访问次数很少的数据放在外存中。如何选择内存中暂留的数据是一个很值得研究的问题,下面介绍一个内存管理中比较常用的算法:内存中的数据以页为基本存储单位,进程的读写操作都针对页来进行。实际内存空间被分割成n页,虚拟内存空间的页数往往要多得多。某一时刻,进程需要访问虚存编号为P的页,该算法的执行步骤如下: a. 首先在内存中查找,如果该页位于内存中,查找成功,转d,否则继续下面的操作; b. 寻找内存中是否存在空页(即没有装载任何数据页的页面),若有,则从外存中读入要查找页,并将该页送至内存中的空页进行存储,然后转d,否则继续下面的操作; c. 在内存中寻找一个访问次数最少的页面(如果存在多个页面的访问次数同时为最少,则选取最早读入数据进入内存的那个页面),从外存中读入要查找页,替换该页。 d. 结束所谓访问次数是指从当前页面进入内存到该时刻被访问的次数,如果该页面以前进入过内存并被其它页面替换,那么前面的访问次数不应计入这个时刻的访问次数中。你的任务是设计一个程序实现上述算法。测试数据将会提供m条读写内存的命令,每条命题提供要求访问的虚拟内存页的编号P。你的程序要求能够模拟整个m条命令的全部执行过程,所有的命令是按照输入的先后执行的,最开始的时候内存中的n页全为空。

Input

第1行为n<10000和m<1000000,分别表示内存页数和读写内存命令条数。接下来有m行,其中第i+1行有一个正整数Pi<=10^9,表示第i条读写内存命令需要访问的虚拟内存页的编号。

Output

仅包含一个正整数,表示在整个模拟过程中,在内存中直接查找成功的次数(即上面的算法只执行步骤a的次数)。

Sample Input

3 8

1

1

2

3

4

2

5

4

Sample Output

1
写在前面:目标达成~
——————————————————————————————————————————————
思路:
读题思题时间长,用堆模拟别慌忙。
map重载离散化,两遍AC四秒躺。
代码:

#include<cstdio>
#include<cstring>
#include<set>
#include<queue>
#include<map>
#include<iostream>
using namespace std;
int n,p,m,ans,tot;
int flag[1000001]; 
map <int,int>ma;
struct os
{
    int num,happen,dis;//num是输入顺序,happen是访问次数,dis是离散化对应的值
    bool operator >(const os &other)const
    {
        if (happen<other.happen) return 0;
        if (happen>other.happen) return 1;
        return num>other.num;
    }
}x;
priority_queue <os,vector<os>,greater<os> >team;
int in()
{
    int t=0;
    char ch=getchar();
    while (ch>'9'||ch<'0') ch=getchar();
    while (ch>='0'&&ch<='9') t=t*10+ch-'0',ch=getchar();
    return t;
}
main()
{
    n=in();
    m=in();
    for (int i=1;i<=m;i++)
    {
        int k;
        p=in();
        if (!ma[p]) {ma[p]=++tot;k=tot;}
        else k=ma[p];
        flag[k]++;
        if (flag[k]>1) {ans++;continue;}
        //a步骤
        x.happen=1;x.num=i;x.dis=k; 
        if (team.size()!=n) {team.push(x);continue;}
        //b步骤
        os y=team.top();
        while (y.happen!=flag[y.dis])
        {
            team.pop();
            y.happen=flag[y.dis];
            team.push(y);
            y=team.top();
        }
        flag[y.dis]=0;team.pop();team.push(x);
        //c步骤。堆中的页面未修改访问次数,所以弹出值时要注意修改
    }
    printf("%d",ans);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值