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(Q \log Q)\)

空间复杂度 \(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 @ 2022-07-09 15:29  空白菌  阅读(41)  评论(0)    收藏  举报