很显然如果不够k的话就不用放回去,如果够了就需要放回去一个,这时候只要放回去的是之后用到的最远的一个就可以了,用一个nxt数组然后堆维护,最后就是弹出堆的时候需要判断一下这一个是否已经放回去了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#define MK make_pair
#define maxn 500055
using namespace std;
int vis[maxn],nxt[maxn],m,a[maxn],k,n,last[maxn];
typedef pair<int,int>pii;
priority_queue<pii>q;
int main(){
scanf("%d%d%d",&m,&k,&n);
for(int i=1;i<=n;i++)scanf("%d",a+i),last[a[i]]=n+1;
for(int i=n;i>=1;i--){
nxt[i]=last[a[i]];
last[a[i]]=i;
}
int ans=0;
for(int i=1;i<=n;i++){
if(vis[a[i]]){q.push(MK(nxt[i],a[i]));}
else if(k){
k--,ans++;
vis[a[i]]=1;
q.push(MK(nxt[i],a[i]));
}else{
while(!vis[q.top().second])q.pop();
int x=q.top().second;q.pop();
vis[x]=0,ans++,vis[a[i]]=1;
q.push(MK(nxt[i],a[i]));
}
}
printf("%d",ans);
return 0;
}