1. 程式人生 > 實用技巧 >SP688 SAM - Toy Cars 貪心

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;
}