NC15688 Operating System

题目链接

题目

题目描述

在学习Operating System的过程中,Glory遇到了这样一个问题,现在有一个大小为可以容纳N个页面的内存,硬盘内的内容被分成M个页面,用1~M来标识,一开始内存里没有任何页面,接下来用户会请求Q个页面,你需要设计一个置换算法,使得缺页发生的次数最少。缺页是指用户请求某个编号的页面,但这个页面没有在内存中的情况。发生缺页之后,你必须要把硬盘内对应的页面调入内存中,如果内存已满,你需要置换掉当前内存中的某个页面。

输入描述

多组数据,请处理到输入结束。
每组数据,第一行为三个整数N,M,Q (0 < N,M,Q <= 50000)
接下来一行Q个数,表示用户请求的页面编号。

输出描述

对于每组数据,输出一个数,表示最少的缺页次数。

示例1

输入

2 3 5
3 1 2 1 2
3 4 5
3 2 1 4 3

输出

3
4

题解

知识点:贪心,优先队列。

显然,OPT算法贪心一下即可,预处理后用优先队列维护。具体可以看我另一篇博客 **“NC20185 [JSOI2010]缓存交换” ** 。

时间复杂度 O(QlogQ)

空间复杂度 O(Q+N)

代码

#include <bits/stdc++.h>
using namespace std;
int a[50007], last[50007], nxt[50007], vis[50007];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m, q;
while (cin >> n >> m >> q) {
for (int i = 0;i < q;i++) cin >> a[i];
memset(last, 0x7f, sizeof(last));///初始化下一位置无穷大,7f是最大,ff会变成负数
memset(vis, 0, sizeof(vis));
for (int i = q - 1;i >= 0;i--) {///倒序遍历,更新右侧最新位置
nxt[i] = last[a[i]];///第 i 个元素的下一个出现位置
last[a[i]] = i;///更新值为a[i]元素的最新位置
}
priority_queue<pair<int, int>> pq; ///优先队列默认从大到小
int cnt = 0;///cnt代替内存使用长度,因为pq每次不管有没有都会插入,而pq长度并非真实长度
for (int i = 0;i < q;i++) {
if (!vis[a[i]]) {
if (cnt >= n) vis[a[pq.top().second]] = 0, pq.pop();
vis[a[i]] = 1;
cnt++;
}
pq.push({ nxt[i],i });///持续插入,并不会导致反复删除同一个重复元素,因为如果出现重复元素一定从序列尾部的元素开始,等价于弹出了尾部元素,更新了到了前面
}
cout << cnt << '\n';
}
return 0;
}
posted @   空白菌  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示