SP688 SAM - Toy Cars 貪心
阿新 • • 發佈:2020-07-30
題目描述
分析
這是一道比較經典的貪心題目
我們要使取玩具的次數儘可能少,那麼當地面上的空間足夠大的時候,我們就直接把玩具放在地板上
如果地面上的空間不夠,我們就將地面上的玩具裡下一次最晚出現的放到架子上
因此,我們要維護一個優先佇列,儲存所有在地板上的玩具,按照出現順序從晚到早排序
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; }