[POI2005]SAM-Toy Cars 贪心+堆

时间:2023-03-09 15:32:31
[POI2005]SAM-Toy Cars 贪心+堆

[POI2005]SAM-Toy Cars

题目:Jasio 是一个三岁的小男孩,他最喜欢玩玩具了,他有n 个不同的玩具,它们都被放在了很高的架子上所以Jasio 拿不到它们;为了让他的房间有足够的空间,在任何时刻地板上都不会有超过k 个玩具. Jasio 在地板上玩玩具. Jasio'的妈妈则在房间里陪他的儿子, 当Jasio 想玩地板上的其他玩具时,他会自己去拿,如果他想玩的玩具在架子上,他的妈妈则会帮他去拿,当她拿玩具的时候,顺便也会将一个地板上的玩具放上架子使得地板上有足够的空间. 他的妈妈很清楚自己的孩子所以他能够预料到Jasio 想玩些什么玩具. 所以她想尽量的使自己去架子上拿玩具的次数尽量的少,应该怎么安排放玩具的顺序呢?

思路:

显然,地板上玩具不到k个时可以直接加,当前在地板上的玩具下一次出现的时候越晚越应

该被换掉,用单调队列维护;

细节:

注意已经在地板上的物品是不用删的,没有影响,但是删掉的话会TLE;

代码

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int N=1e6+7;
const int inf=1<<30;
struct toy{
int x,nt;
toy(){};
toy(int X,int Y){
x=X;
nt=Y;
}
friend bool operator <(const toy &x,const toy &y){
return x.nt<y.nt;
}
}a[N],b[N];
int n,m,k,ans,cnt;
int vis[N],last[N];
priority_queue<toy> q;
int main(){
scanf("%d%d%d",&n,&k,&m);
for(int i=1;i<=m;i++){
int x;
scanf("%d",&x);
a[i].x=x;
a[last[x]].nt=i;
last[x]=i;
}
for(int i=1;i<=m;i++) if(a[i].nt==0) a[i].nt=inf;
// cout<<"\n";
for(int i=1;i<=m;i++){
if(vis[a[i].x]){
// cnt=0;
// while(q.top().x!=a[i].x){
// b[++cnt]=q.top();
// q.pop();
// }
// q.pop();
// cout<<"--->"<<a[i].x<<" "<<a[i].nt<<"\n";
q.push(toy(a[i].x,a[i].nt));
// k++;
// for(int j=1;j<=cnt;j++){
// q.push(b[j]);
// }
continue;
}
if(!k){
toy t=q.top();
q.pop();
k++;
vis[t.x]=0;
// cout<<"-->"<<t.x<<"\n";
}
// cout<<i<<" "<<a[i].x<<"\n";
q.push(toy(a[i].x,a[i].nt));
k--;
vis[a[i].x]=1;
ans++;
}
cout<<ans;
}