普通版:

#include <bits/stdc++.h>
using namespace std;
int n, m;
map<int,int> mp;//用于负责构造nexti[i]数组
bool boo[100050];//表示Cache中的内存。boo[2]=1表示a[2]在Cache中
int nexti[100050];//nexti[1]=3表示a[1]接下来最近的与a[1]相同的是a[3]
int ar[100050];
priority_queue<int> q;//储存最近的与Cache中的元素相同的元素的下标
                      //boo中有多少个元素等于1,则q中就至少有这些元素
int num, ans;//num表示Cache中已经有多少个元素,ans记录答案
 
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) scanf("%d", &ar[i]);
    for(int i = n; i > 0; --i)//构造nexti[i]数组,表示下一个与a[i]相同的数的下标是几,不纯在则为N
    {
        if(mp[ar[i]] == 0)  nexti[i] = 100050;
        else    nexti[i] = mp[ar[i]];
        mp[ar[i]] = i;//用mp[a[i]]=i记录上一次a[i]的下标i,下一次遇到a[i]时next[i]=mp[a[i]]=该下标
    }
    
    for(int i = 1; i <= n; ++i)
    {
        if(boo[i] == 0)//a[i]若不在Cache中
        {
            ans++;//进行缺失操作,答案数++
            if(num < m)//Cache没有满
            {
                num++;//Cache中元素+1
                boo[nexti[i]]=1;//标记将该a[i]存入Cache,即下一次遇到a[i]时显示a[i]在Cache中
                                //等价于把下一次出现的a[i]的下标标记
                q.push(nexti[i]);//把下一次出现a[i]的位置的下标存入q
            }
            else//Cache满了
            {
                boo[q.top()] = 0;//删掉最晚要用再次到的,即q中储存的所有下标中下标最大的
                q.pop();
                boo[nexti[i]]=1;//存入当前要用的a[i],等价于标记下一次出现a[i]的位置的下标
                q.push(nexti[i]);//把下一次出现a[i]的位置的下标存入q
            }
        }
        else//a[i]在Cache中,不需要进行缺失操作,但需要把更大的下标存入q并标记下一次a[i]任在Cache中
        {
            boo[nexti[i]] = 1;//a[i]还在Cache中,下一次遇到a[i]时任然显示a[i]在Cache中
                              //等价于再把下一次出现的a[i]的下标标记
            q.push(nexti[i]);//把下一次出现a[i]的位置的下标存入q
        }
    }
    printf("%d\n", ans);
    return 0;
}

遍历时无论a[i]是否在Cache中,下次遇到a[i]时,都要显示a[i]在Cache中 并且要将下一次a[i]出现的位置的下标存入q 所以这两行操作在遍历每个a[i]时都要进行,故可以写在if外面进行简化 简化版

#include <bits/stdc++.h>
using namespace std;
int n, m;
map<int,int> mp;
bool boo[100050];//表示Cache中的内存。boo[2]=1表示a[2]在Cache中
int nexti[100050];//nexti[1]=3表示a[1]接下来最近的与a[1]相同的是a[3]
int ar[100050];
priority_queue<int> q;//储存最近的与Cache中的元素相同的元素的下标
                      //boo中有多少个元素等于1,则q中就至少有这些元素甚至更多
int num, ans;//num表示Cache中已经有多少个元素,ans记录答案
 
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) scanf("%d", &ar[i]);
    for(int i = n; i > 0; --i)//构造nexti[i]数组,表示下一个与a[i]相同的数的下标是几,不纯在则为N
    {
        if(mp[ar[i]] == 0)  nexti[i] = 100050;
        else    nexti[i] = mp[ar[i]];
        mp[ar[i]] = i;//用mp[a[i]]=i记录上一次a[i]的下标i,下一次遇到a[i]时next[i]=mp[a[i]]=该下标
    }
    
    for(int i = 1; i <= n; ++i)
    {
        if(boo[i] == 0)//a[i]若不在Cache中
        {
            ans++;//进行缺失操作,答案数++
            if(num < m) num++;//Cache没有满,Cache中元素+1  
            else//Cache满了
            {
                boo[q.top()] = 0;//删掉最晚要用再次到的,即q中储存的所有下标中下标最大的
                q.pop();   
            }
        }
        boo[nexti[i]] = 1;//标记将该a[i]存入Cache,即下一次遇到a[i]时显示a[i]在Cache中
                          //等价于把下一次出现的a[i]的下标标记
        q.push(nexti[i]);//把下一次出现a[i]的位置的下标存入q
    }
    printf("%d\n", ans);
    return 0;
}