BSOJ:3768 玩具车--贪心+堆

29 篇文章 0 订阅
8 篇文章 0 订阅
3768 -- 【模拟试题】玩具车
Description
  Jasio 是一个三岁的小男孩,他最喜欢玩玩具了,他有n 个不同的玩具,它们都被放在了很高的架子上,所以Jasio 拿不到它们。为了让他的房间有足够的空间,在任何时刻地板上都不会有超过k个玩具。
  Jasio在地板上玩玩具。Jasio的妈妈则在房间里陪他的儿子,当Jasio 想玩地板上的其他玩具时,他会自己去拿,如果他想玩的玩具在架子上,他的妈妈则会帮他去拿,当她拿玩具的时候,顺便也会将一个地板上的玩具放上架子使得地板上有足够的空间。
  他的妈妈很清楚自己的孩子,所以他能够预料到Jasio想玩些什么玩具。所以她想尽量的使自己去架子上拿玩具的次数尽量的少,应该怎么安排放玩具的顺序呢?
Input
  输入文件的第一行三个整数:n, k, p (1<=k<=n <=100000, 1<=p<=500000),分别表示玩具的个数,地板上玩具的最多个数以及Jasio他想玩玩具的序列个数,接下来p行每行描述一个整数表示Jasio想玩的玩具编号。
Output
  输出文件只有一行为一个整数,表示Jasio 的妈妈最少要拿多少次玩具。
Sample Input
3 2 7
1
2
3
1
3
1
2
Sample Output
4
Hint
【数据范围】
  对于50%的数据1<=n<=500,1<=k<=200,1<=p<=2000

  对于100%的数据1<=n<=100000,1<=k<=100000,1<=p<=500000


贪心策略是个人都想得到吧..当空间不足时,删除下一个使用时间最晚的玩具..毕竟样例给得很清楚了。

那么这个就是明显的使用堆了,删除时取堆顶pop即可,当然记一个hash记录这个玩具在不在地板上。

然而写的时候WA了无数次..原因一是当发现地板上有这个玩具时,没有把新的next时间截给push进去,导致时间乱完了..

二是改正这个错误之后,一开始我只是单纯地把k个元素push进去,其实开始时必须要把地板铺满才能结束预处理,也即当hash[a[i]]=1的时候要记录再多入一个,不然k个push完后不一定能铺的满地板。

使用堆的时候注意每次pop无效数据。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<queue>
#define ll long long
#define pa pair<ll,ll>
using namespace std;
priority_queue<pa> Q;
inline ll read()
{
	ll bj=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-')bj=-1;
		ch=getchar();
	}
	ll ret=0;
	while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
	return ret*bj;
}
ll n,k,p,a[1000005]={0},pos[1000005]={0},next[1000005]={0};
bool ha[1000005]={0};
void init()
{
	n=read();k=read();p=read();
	for(ll i=1;i<=p;i++)a[i]=read();
	for(ll i=1;i<=p;i++)
	{
		if(!pos[a[i]]){pos[a[i]]=i;continue;}
		else 
		{
			next[pos[a[i]]]=i;
			pos[a[i]]=i;
		}
	}
	for(ll i=1;i<=p;i++)if(next[i]==0)next[i]=p+1;
	
} 
void greed()
{
	ll ans=0;
	for(ll i=1;i<=k;i++)
	{
		if(ha[a[i]])
		{
			Q.push(make_pair(next[i],a[i]));
			k++;
			continue;
		}
		ans++;
		Q.push(make_pair(next[i],a[i]));
		ha[a[i]]=1;
	}
	for(ll i=1;i<=p;i++)
	{
		if(ha[a[i]])
		{
			Q.push(make_pair(next[i],a[i]));
			continue;
		}
	    while(!Q.empty()&&ha[Q.top().second]==0)Q.pop();
		ha[Q.top().second]=0;
		Q.pop();
		Q.push(make_pair(next[i],a[i]));
		ha[a[i]]=1;
		ans++;
	}
	printf("%lld\n",ans);
}
int main()
{
	init();
	greed();
return 0;
}
/*
3 2 7
1
2
3
1
3
1
2
*/


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值