SP688 SAM - Toy Cars 贪心

题目描述



分析

这是一道比较经典的贪心题目
我们要使取玩具的次数尽可能少,那么当地面上的空间足够大的时候,我们就直接把玩具放在地板上
如果地面上的空间不够,我们就将地面上的玩具里下一次最晚出现的放到架子上
因此,我们要维护一个优先队列,存储所有在地板上的玩具,按照出现顺序从晚到早排序

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\n",ans);
    return 0;
}
posted @ 2020-07-30 16:06  liuchanglc  阅读(177)  评论(0编辑  收藏  举报