题目链接

https://ac.nowcoder.com/acm/problem/15688

题意

容量为n的内存,有1-m编号的页面,有q个请求,每个请求包含一个页面,内存里面没有这个页面的话,就会记录一次缺页,并放入内存,内存满了就会置换其中一个页面,求缺页次数最少。

思路

如需置换,置换晚出现的页面。

代码

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int MINF = 0x3f3f3f;
const double eps = 1e-9;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;

const int N = 50000;
int n, m, q;
int a[N + 5];
int vis[N + 5]; //a[i] 下一次出现的序号
bool bl[N + 5]; //页面是否有被访问
map<int, int> mp; //a[i] 出现的序号

void solve() {
    while (cin >> n >> m >> q) {
        mp.clear();
        ll cnt = 0;
        ll num = 0; // 内存里面页面有多少,注意不要用堆的size
        priority_queue<ll, vector<ll>, less<ll>> qu; //记录下一次出现晚的编号
        memset(bl, false, sizeof bl);
        memset(vis, 0, sizeof vis);
        for (int i = 1; i <= q; i++)
            scanf("%d", &a[i]);
        for (int i = q; i >= 1; i--) {
          	//如果之后没有再出现该内存的话,我们就将其vis置为q + 1(一定不会被访问的结点)
            if (mp.find(a[i]) == mp.end())
                vis[i] = q + 1;
            else
                vis[i] = mp[a[i]];
            mp[a[i]] = i;
        }
        for (int i = 1; i <= q; i++) {
          	//如果页面没有被访问
            if (!bl[i]) {
              	//记录缺页
                cnt++;
                if (num < n) {
                  	//内存未满
                    num++;
                } else {
                  	//内存已满,将下一次出现次数晚的先删掉
                    bl[qu.top()] = false;
                    qu.pop();
                }
            }
          	//更新该页面下一次出现的序号
            bl[vis[i]] = true;
            qu.push(vis[i]);
        }
        cout << cnt << '\n';
    }
}

int main() {
    int _ = 1;
//    scanf("%d", &_);
    while (_--) {
        solve();
    }
    return 0;
}