题目描述
分析
这是一道比较经典的贪心题目 我们要使取玩具的次数尽可能少,那么当地面上的空间足够大的时候,我们就直接把玩具放在地板上 如果地面上的空间不够,我们就将地面上的玩具里下一次最晚出现的放到架子上 因此,我们要维护一个优先队列,存储所有在地板上的玩具,按照出现顺序从晚到早排序
struct asd{
int num,tim;
asd(){}
asd(int aa,int bb){
num=aa,tim=bb;
}
bool operator < (const asd& A)const{
return tim<A.tim;
}
};
priority_queue<asd> q;
同时,我们还要用一个数组$nex$记录当前元素上一次出现的位置 这个东西我们倒序枚举处理就可以 要注意的是,因为优先队列的删除操作不好处理,所以我们想要从地板上拿出一个玩具,只需要把地板能容纳的玩具数加一就可以 因为要拿出玩具的最晚出现时间一定要早,不会对后面的产生影响
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int lat[maxn],nex[maxn],a[maxn];
bool vis[maxn];
struct asd{
int num,tim;
asd(){}
asd(int aa,int bb){
num=aa,tim=bb;
}
bool operator < (const asd& A)const{
return tim<A.tim;
}
};
priority_queue<asd> q;
int main(){
int n,k,nn;
scanf("%d%d%d",&n,&k,&nn);
for(int i=1;i<=nn;i++){
scanf("%d",&a[i]);
}
for(int i=nn;i>=1;i--){
if(lat[a[i]]==0) nex[i]=0x3f3f3f3f;
else nex[i]=lat[a[i]];
lat[a[i]]=i;
}
int ans=0;
for(int i=1;i<=nn;i++){
if(vis[a[i]]==1){
k++;
q.push(asd(a[i],nex[i]));
} else if(q.size()<k){
vis[a[i]]=1;
q.push(asd(a[i],nex[i]));
ans++;
} else {
int now=q.top().num;
vis[now]=0;
q.pop();
vis[a[i]]=1;
q.push(asd(a[i],nex[i]));
ans++;
}
}
printf("%d
",ans);
return 0;
}