[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;
}
posted @ 2020-08-26 21:19  Aswert  阅读(105)  评论(0编辑  收藏  举报